18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 client - read handshake message
3818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha256.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_client.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_client_i.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len);
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len);
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *in_data, size_t *in_len);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *in_data, size_t *in_len)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, i;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 cipher_suite;
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u16 tls_version;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4)
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ServerHello)", *pos);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length */
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left)
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerHello */
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion server_version */
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tls_version = WPA_GET_BE16(pos);
791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!tls_version_ok(tls_version)) {
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "ServerHello %u.%u", pos[0], pos[1]);
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_PROTOCOL_VERSION);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		   tls_version_str(tls_version));
901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	conn->rl.tls_version = tls_version;
911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Random random */
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < TLS_RANDOM_LEN)
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RANDOM_LEN;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->server_random, TLS_RANDOM_LEN);
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionID session_id */
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_id_len && conn->session_id_len == *pos &&
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 1 + conn->session_id_len;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_resumed = 1;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->session_id_len = *pos;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(conn->session_id, pos, conn->session_id_len);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += conn->session_id_len;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->session_id, conn->session_id_len);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CipherSuite cipher_suite */
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cipher_suite = WPA_GET_BE16(pos);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < conn->num_cipher_suites; i++) {
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cipher_suite == conn->cipher_suites[i])
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i == conn->num_cipher_suites) {
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "cipher suite 0x%04x", cipher_suite);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_ILLEGAL_PARAMETER);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "cipher suite for a resumed connection (0x%04x != "
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "0x%04x)", cipher_suite, conn->prev_cipher_suite);
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_ILLEGAL_PARAMETER);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_INTERNAL_ERROR);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->prev_cipher_suite = cipher_suite;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CompressionMethod compression_method */
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_COMPRESSION_NULL) {
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "compression 0x%02x", *pos);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_ILLEGAL_PARAMETER);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end != pos) {
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: ServerHello extensions */
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "end of ServerHello", pos, end - pos);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_ticket_included && conn->session_ticket_cb) {
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: include SessionTicket extension if one was included in
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * ServerHello */
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = conn->session_ticket_cb(
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->session_ticket_cb_ctx, NULL, 0,
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->client_random, conn->server_random,
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->master_secret);
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "indicated failure");
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_HANDSHAKE_FAILURE);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->use_session_ticket = !!res;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((conn->session_resumed || conn->use_session_ticket) &&
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_derive_keys(conn, NULL, 0)) {
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_INTERNAL_ERROR);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdecode_error:
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *in_data, size_t *in_len)
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, list_len, cert_len, idx;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *chain = NULL, *last = NULL, *cert;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reason;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu)", (unsigned long) left);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_server_key_exchange(conn, ct, in_data,
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_certificate_request(conn, ct, in_data,
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_server_hello_done(conn, ct, in_data,
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     in_len);
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected Certificate/"
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ServerKeyExchange/CertificateRequest/"
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ServerHelloDone)", type);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG,
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "TLSv1: Received Certificate (certificate_list len %lu)",
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) len);
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque ASN.1Cert<2^24-1>;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     ASN.1Cert certificate_list<1..2^24-1>;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } Certificate;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(left=%lu)", (unsigned long) left);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	list_len = WPA_GET_BE24(pos);
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((size_t) (end - pos) != list_len) {
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu left=%lu)",
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) list_len,
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) (end - pos));
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = 0;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos < 3) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "certificate_list");
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_DECODE_ERROR);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert_len = WPA_GET_BE24(pos);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((size_t) (end - pos) < cert_len) {
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length (len=%lu left=%lu)",
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) cert_len,
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_DECODE_ERROR);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) idx, (unsigned long) cert_len);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (idx == 0) {
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_public_key_free(conn->server_rsa_key);
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tls_parse_cert(pos, cert_len,
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   &conn->server_rsa_key)) {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "the certificate");
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  TLS_ALERT_BAD_CERTIFICATE);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				x509_certificate_chain_free(chain);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_parse(pos, cert_len);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "the certificate");
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_BAD_CERTIFICATE);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last == NULL)
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			chain = cert;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			last->next = cert;
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = cert;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx++;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert_len;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred &&
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
369c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					    &reason, conn->disable_time_checks)
370c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	    < 0) {
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int tls_reason;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "validation failed (reason=%d)", reason);
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (reason) {
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_BAD_CERTIFICATE:
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_REVOKED:
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_EXPIRED:
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNKNOWN_CA:
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNKNOWN_CA;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		x509_certificate_chain_free(chain);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	x509_certificate_chain_free(chain);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_KEY_EXCHANGE;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
412b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtstatic unsigned int count_bits(const u8 *val, size_t len)
413b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{
414b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	size_t i;
415b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	unsigned int bits;
416b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	u8 tmp;
417b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
418b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	for (i = 0; i < len; i++) {
419b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (val[i])
420b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt			break;
421b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
422b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (i == len)
423b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		return 0;
424b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
425b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	bits = (len - i - 1) * 8;
426b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	tmp = val[i];
427b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	while (tmp) {
428b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		bits++;
429b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tmp >>= 1;
430b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
431b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
432b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	return bits;
433b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt}
434b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
435b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
437818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					const u8 *buf, size_t len,
438818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					tls_key_exchange key_exchange)
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
440818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	const u8 *pos, *end, *server_params, *server_params_end;
441818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	u8 alert;
442b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	unsigned int bits;
443fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	u16 val;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsv1_client_free_dh(conn);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = buf + len;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3)
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
452818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	server_params = pos;
453fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	val = WPA_GET_BE16(pos);
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
455fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (val == 0 || val > (size_t) (end - pos)) {
456fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %u", val);
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
459fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	conn->dh_p_len = val;
460b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	bits = count_bits(pos, conn->dh_p_len);
461b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (bits < 768) {
462b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Reject under 768-bit DH prime (insecure; only %u bits)",
463b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt			   bits);
464b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "TLSv1: Rejected DH prime",
465b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt			    pos, conn->dh_p_len);
466b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		goto fail;
467b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_p = os_malloc(conn->dh_p_len);
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_p == NULL)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->dh_p, pos, conn->dh_p_len);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->dh_p_len;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->dh_p, conn->dh_p_len);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3)
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
478fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	val = WPA_GET_BE16(pos);
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
480fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (val == 0 || val > (size_t) (end - pos))
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
482fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	conn->dh_g_len = val;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_g = os_malloc(conn->dh_g_len);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_g == NULL)
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->dh_g, pos, conn->dh_g_len);
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->dh_g_len;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->dh_g, conn->dh_g_len);
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3)
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
495fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	val = WPA_GET_BE16(pos);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
497fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (val == 0 || val > (size_t) (end - pos))
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
499fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	conn->dh_ys_len = val;
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_ys = os_malloc(conn->dh_ys_len);
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_ys == NULL)
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->dh_ys, pos, conn->dh_ys_len);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->dh_ys_len;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->dh_ys, conn->dh_ys_len);
507818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	server_params_end = pos;
508818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
509818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (key_exchange == TLS_KEY_X_DHE_RSA) {
510818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
511818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		int hlen;
512818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
513818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (conn->rl.tls_version == TLS_VERSION_1_2) {
514818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TLSV12
515818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			/*
516818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * RFC 5246, 4.7:
517818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * TLS v1.2 adds explicit indication of the used
518818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * signature and hash algorithms.
519818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *
520818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * struct {
521818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   HashAlgorithm hash;
522818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   SignatureAlgorithm signature;
523818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * } SignatureAndHashAlgorithm;
524818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 */
525818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			if (end - pos < 2)
526818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				goto fail;
527818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			if (pos[0] != TLS_HASH_ALG_SHA256 ||
528818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			    pos[1] != TLS_SIGN_ALG_RSA) {
529818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
530818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					   pos[0], pos[1]);
531818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				goto fail;
532818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			}
533818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			pos += 2;
534818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
535818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hlen = tlsv12_key_x_server_params_hash(
536818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->rl.tls_version, conn->client_random,
537818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->server_random, server_params,
538818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				server_params_end - server_params, hash);
539818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#else /* CONFIG_TLSV12 */
540818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			goto fail;
541818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TLSV12 */
542818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		} else {
543818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hlen = tls_key_x_server_params_hash(
544818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->rl.tls_version, conn->client_random,
545818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->server_random, server_params,
546818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				server_params_end - server_params, hash);
547818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
548818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
549818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (hlen < 0)
550818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			goto fail;
551818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
552818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			    hash, hlen);
553818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
554818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (tls_verify_signature(conn->rl.tls_version,
555818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 conn->server_rsa_key,
556818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 hash, hlen, pos, end - pos,
557818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 &alert) < 0)
558818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			goto fail;
559818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	}
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail:
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsv1_client_free_dh(conn);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(Left=%lu)", (unsigned long) left);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_certificate_request(conn, ct, in_data,
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_server_hello_done(conn, ct, in_data,
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     in_len);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ServerKeyExchange/"
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CertificateRequest/ServerHelloDone)", type);
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "with the selected cipher suite");
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
638818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
639818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		      suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
640818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (tlsv1_process_diffie_hellman(conn, pos, len,
641818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt						 suite->key_exchange) < 0) {
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_DECODE_ERROR);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_CERTIFICATE_REQUEST;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len)
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(left=%lu)", (unsigned long) left);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_server_hello_done(conn, ct, in_data,
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     in_len);
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected CertificateRequest/"
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ServerHelloDone)", type);
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->certificate_requested = 1;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_HELLO_DONE;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const u8 *in_data, size_t *in_len)
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(left=%lu)", (unsigned long) left);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ServerHelloDone)", type);
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_KEY_EXCHANGE;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 u8 ct, const u8 *in_data,
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 size_t *in_len)
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->use_session_ticket) {
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int res;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "rejected SessionTicket");
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->use_session_ticket = 0;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Notify upper layers that SessionTicket failed */
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = conn->session_ticket_cb(
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->session_ticket_cb_ctx, NULL, 0, NULL,
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				NULL, NULL);
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (res < 0) {
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "callback indicated failure");
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  TLS_ALERT_HANDSHAKE_FAILURE);
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->state = SERVER_CERTIFICATE;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return tls_process_certificate(conn, ct, in_data,
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 1) {
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received data 0x%x", *pos);
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for record layer");
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_INTERNAL_ERROR);
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = pos + 1 - in_data;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_FINISHED;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *in_data, size_t *in_len)
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, hlen;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 verify_data[TLS_VERIFY_DATA_LEN];
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Finished",
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) left);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_DECODE_ERROR);
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "type 0x%x", pos[0]);
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos + 1);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 4;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu > left=%lu)",
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_DECODE_ERROR);
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != TLS_VERIFY_DATA_LEN) {
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "in Finished: %lu (expected %d)",
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_DECODE_ERROR);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, TLS_VERIFY_DATA_LEN);
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
9161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
9171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_server == NULL ||
9181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
9191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    < 0) {
9201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  TLS_ALERT_INTERNAL_ERROR);
9221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_server = NULL;
9231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
9241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_server = NULL;
9261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
9271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_server == NULL ||
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_INTERNAL_ERROR);
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_server = NULL;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_server = NULL;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_server == NULL ||
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_INTERNAL_ERROR);
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_server = NULL;
9501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
9511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
9541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf(conn->rl.tls_version,
9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    conn->master_secret, TLS_MASTER_SECRET_LEN,
9581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "server finished", hash, hlen,
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    verify_data, TLS_VERIFY_DATA_LEN)) {
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_DECRYPT_ERROR);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			verify_data, TLS_VERIFY_DATA_LEN);
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
970818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
971818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			  TLS_ALERT_DECRYPT_ERROR);
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = (conn->session_resumed || conn->use_session_ticket) ?
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		CHANGE_CIPHER_SPEC : ACK_FINISHED;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *in_data, size_t *in_len,
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 **out_data, size_t *out_len)
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  TLS_ALERT_UNEXPECTED_MESSAGE);
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, left);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_data = os_malloc(left);
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*out_data) {
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(*out_data, pos, left);
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*out_len = left;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *buf, size_t *len,
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   u8 **out_data, size_t *out_len)
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_ALERT) {
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 2) {
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_DECODE_ERROR);
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   buf[0], buf[1]);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 2;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = FAILED;
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t hr_len = WPA_GET_BE24(buf + 1);
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hr_len > *len - 4) {
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  TLS_ALERT_DECODE_ERROR);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 4 + hr_len;
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_HELLO:
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_server_hello(conn, ct, buf, len))
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_CERTIFICATE:
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate(conn, ct, buf, len))
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_KEY_EXCHANGE:
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_server_key_exchange(conn, ct, buf, len))
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_CERTIFICATE_REQUEST:
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate_request(conn, ct, buf, len))
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_HELLO_DONE:
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_server_hello_done(conn, ct, buf, len))
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_CHANGE_CIPHER_SPEC:
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_FINISHED:
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_server_finished(conn, ct, buf, len))
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case ACK_FINISHED:
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (out_data &&
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tls_process_application_data(conn, ct, buf, len, out_data,
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 out_len))
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "while processing received message",
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->state);
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_verify_hash_add(&conn->verify, buf, *len);
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1096