18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - read handshake message
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2006-2011, 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_server.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server_i.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *in_data, size_t *in_len)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *c;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, i, j;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 cipher_suite;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 num_suites;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int compr_null_found;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 ext_type, ext_len;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4)
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ClientHello)", *pos);
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello");
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length */
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ClientHello */
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion client_version */
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->client_version = WPA_GET_BE16(pos);
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d",
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   conn->client_version >> 8, conn->client_version & 0xff);
831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->client_version < TLS_VERSION_1) {
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "ClientHello %u.%u",
861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   conn->client_version >> 8,
871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   conn->client_version & 0xff);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_PROTOCOL_VERSION);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (TLS_VERSION == TLS_VERSION_1)
951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1;
961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (conn->client_version >= TLS_VERSION_1_2)
981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1_2;
991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (conn->client_version > TLS_VERSION_1_1)
1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1_1;
1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = conn->client_version;
1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		   tls_version_str(conn->rl.tls_version));
1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Random random */
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < TLS_RANDOM_LEN)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RANDOM_LEN;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->client_random, TLS_RANDOM_LEN);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionID session_id */
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 1 + *pos;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for session resumption */
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CipherSuite cipher_suites<2..2^16-1> */
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = WPA_GET_BE16(pos);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites",
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_suites & 1)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites /= 2;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cipher_suite = 0;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = pos;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < num_suites; j++) {
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u16 tmp = WPA_GET_BE16(c);
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			c += 2;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!cipher_suite && tmp == conn->cipher_suites[i]) {
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cipher_suite = tmp;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += num_suites * 2;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cipher_suite) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite "
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available");
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->cipher_suite = cipher_suite;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CompressionMethod compression_methods<1..2^8-1> */
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = *pos++;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods",
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	compr_null_found = 0;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_suites; i++) {
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos++ == TLS_COMPRESSION_NULL)
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			compr_null_found = 1;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!compr_null_found) {
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL "
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "compression");
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos == 1) {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the "
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "end of ClientHello: 0x%02x", *pos);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos >= 2) {
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Extension client_hello_extension_list<0..2^16-1> */
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ext_len = WPA_GET_BE16(pos);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello "
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "extensions", ext_len);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos != ext_len) {
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello "
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "extension list length %u (expected %u)",
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ext_len, (unsigned int) (end - pos));
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto decode_error;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * struct {
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   ExtensionType extension_type (0..65535)
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   opaque extension_data<0..2^16-1>
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * } Extension;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos < end) {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_type field");
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_type = WPA_GET_BE16(pos);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_data length field");
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_len = WPA_GET_BE16(pos);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < ext_len) {
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_data field");
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension "
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "type %u", ext_type);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello "
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Extension data", pos, ext_len);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ext_type == TLS_EXT_SESSION_TICKET) {
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(conn->session_ticket);
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->session_ticket = os_malloc(ext_len);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (conn->session_ticket) {
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					os_memcpy(conn->session_ticket, pos,
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  ext_len);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					conn->session_ticket_len = ext_len;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ext_len;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to "
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "ServerHello");
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_HELLO;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdecode_error:
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello");
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   TLS_ALERT_DECODE_ERROR);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate(struct tlsv1_server *conn, u8 ct,
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *in_data, size_t *in_len)
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, list_len, cert_len, idx;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *chain = NULL, *last = NULL, *cert;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reason;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu)", (unsigned long) left);
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Client did not include "
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Certificate");
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_client_key_exchange(conn, ct, in_data,
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected Certificate/"
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientKeyExchange)", type);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "TLSv1: Received Certificate (certificate_list len %lu)",
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) len);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque ASN.1Cert<2^24-1>;
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     ASN.1Cert certificate_list<1..2^24-1>;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } Certificate;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(left=%lu)", (unsigned long) left);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	list_len = WPA_GET_BE24(pos);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((size_t) (end - pos) != list_len) {
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu left=%lu)",
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) list_len,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) (end - pos));
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = 0;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos < 3) {
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "certificate_list");
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert_len = WPA_GET_BE24(pos);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((size_t) (end - pos) < cert_len) {
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length (len=%lu left=%lu)",
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) cert_len,
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) idx, (unsigned long) cert_len);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (idx == 0) {
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_public_key_free(conn->client_rsa_key);
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tls_parse_cert(pos, cert_len,
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   &conn->client_rsa_key)) {
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "the certificate");
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   TLS_ALERT_BAD_CERTIFICATE);
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				x509_certificate_chain_free(chain);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_parse(pos, cert_len);
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "the certificate");
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_BAD_CERTIFICATE);
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last == NULL)
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			chain = cert;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			last->next = cert;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = cert;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx++;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert_len;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
437c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					    &reason, 0) < 0) {
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int tls_reason;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "validation failed (reason=%d)", reason);
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (reason) {
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_BAD_CERTIFICATE:
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_REVOKED:
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_EXPIRED:
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNKNOWN_CA:
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNKNOWN_CA;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		x509_certificate_chain_free(chain);
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	x509_certificate_chain_free(chain);
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_KEY_EXCHANGE;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange_rsa(
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *out;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t outlen, outbuflen;
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 encr_len;
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int use_random = 0;
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2) {
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	encr_len = WPA_GET_BE16(pos);
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
4961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (pos + encr_len > end) {
4971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientKeyExchange "
4981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "format: encr_len=%u left=%u",
4991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   encr_len, (unsigned int) (end - pos));
5001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
5021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
5031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuflen = outlen = end - pos;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ?
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			outlen : TLS_PRE_MASTER_SECRET_LEN);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out == NULL) {
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   ProtocolVersion client_version;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   opaque random[46];
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } PreMasterSecret;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   public-key-encrypted PreMasterSecret pre_master_secret;
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } EncryptedPreMasterSecret;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Note: To avoid Bleichenbacher attack, we do not report decryption or
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parsing errors from EncryptedPreMasterSecret processing to the
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * client. Instead, a random pre-master secret is used to force the
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * handshake to fail.
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key,
5331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						 pos, encr_len,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 out, &outlen) < 0) {
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt "
5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "PreMasterSecret (encr_len=%u outlen=%lu)",
5371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   encr_len, (unsigned long) outlen);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) {
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret "
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length %lu", (unsigned long) outlen);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!use_random && WPA_GET_BE16(out) != conn->client_version) {
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Client version in "
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientKeyExchange does not match with version in "
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientHello");
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (use_random) {
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret "
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to avoid revealing information about private key");
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		outlen = TLS_PRE_MASTER_SECRET_LEN;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_get_random(out, outlen)) {
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "data");
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(out);
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, out, outlen);
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(out, 0, outbuflen);
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(out);
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange_dh_anon(
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *dh_yc;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 dh_yc_len;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *shared;
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t shared_len;
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   select (PublicValueEncoding) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case implicit: struct { };
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case explicit: opaque dh_Yc<1..2^16-1>;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   } dh_public;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ClientDiffieHellmanPublic;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic",
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, end - pos);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == pos) {
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding "
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "not supported");
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value "
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length");
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_yc_len = WPA_GET_BE16(pos);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_yc = pos + 2;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_yc + dh_yc_len > end) {
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow "
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(length %d)", dh_yc_len);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    dh_yc, dh_yc_len);
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->dh_secret == NULL) {
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available");
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	shared_len = conn->cred->dh_p_len;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	shared = os_malloc(shared_len);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (shared == NULL) {
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "DH");
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* shared = Yc^secret mod p */
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret,
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret_len,
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->cred->dh_p, conn->cred->dh_p_len,
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   shared, &shared_len)) {
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(shared);
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			shared, shared_len);
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(conn->dh_secret, 0, conn->dh_secret_len);
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->dh_secret);
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret = NULL;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, shared, shared_len);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(shared, 0, shared_len);
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(shared);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len)
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_key_exchange keyx;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange "
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(Left=%lu)", (unsigned long) left);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange "
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ClientKeyExchange)", type);
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange");
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = TLS_KEY_X_NULL;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = suite->key_exchange;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keyx == TLS_KEY_X_DH_anon &&
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0)
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keyx != TLS_KEY_X_DH_anon &&
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_process_client_key_exchange_rsa(conn, pos, end) < 0)
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CERTIFICATE_VERIFY;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *in_data, size_t *in_len)
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t hlen, buflen;
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf;
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 slen;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Client did not include "
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "CertificateVerify");
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_change_cipher_spec(conn, ct, in_data,
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      in_len);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify "
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message (len=%lu)", (unsigned long) left);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify "
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message length (len=%lu != left=%lu)",
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) {
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected CertificateVerify)", type);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify");
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   Signature signature;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } CertificateVerify;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hpos = hash;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version == TLS_VERSION_1_2) {
8451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * RFC 5246, 4.7:
8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * TLS v1.2 adds explicit indication of the used signature and
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * hash algorithms.
8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *
8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * struct {
8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   HashAlgorithm hash;
8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   SignatureAlgorithm signature;
8531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * } SignatureAndHashAlgorithm;
8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
8551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (end - pos < 2) {
8561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
8581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
8591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
8601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (pos[0] != TLS_HASH_ALG_SHA256 ||
8611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    pos[1] != TLS_SIGN_ALG_RSA) {
8621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/"
8631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "signature(%u) algorithm",
8641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   pos[0], pos[1]);
8651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
8671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
8681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
8691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos += 2;
8701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
8721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_cert == NULL ||
8731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
8741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    0) {
8751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_cert = NULL;
8761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
8781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
8791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
8801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_cert = NULL;
8811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
8821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
8831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == SIGN_ALG_RSA) {
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hlen = MD5_MAC_LEN;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify.md5_cert == NULL ||
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0)
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->verify.md5_cert = NULL;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->verify.sha1_cert = NULL;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hpos += MD5_MAC_LEN;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.md5_cert, NULL, NULL);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_cert = NULL;
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_cert == NULL ||
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_cert = NULL;
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_cert = NULL;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == SIGN_ALG_RSA)
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hlen += MD5_MAC_LEN;
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
9161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2) {
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	slen = WPA_GET_BE16(pos);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < slen) {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->client_rsa_key == NULL) {
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify "
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "signature");
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = end - pos;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(end - pos);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key,
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    pos, end - pos, buf, &buflen) < 0)
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf, buflen);
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
9601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *
9621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * DigestInfo ::= SEQUENCE {
9631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   digestAlgorithm DigestAlgorithm,
9641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   digest OCTET STRING
9651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * }
9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *
9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
9681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *
9691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * DER encoded DigestInfo for SHA256 per RFC 3447:
9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
9711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * H
9721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
9731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (buflen >= 19 + 32 &&
9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01"
9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0)
9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		{
9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = "
9781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "SHA-256");
9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memmove(buf, buf + 19, buflen - 19);
9801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			buflen -= 19;
9811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else {
9821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized "
9831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "DigestInfo");
9841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_free(buf);
9851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_DECRYPT_ERROR);
9871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
9881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
9901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) {
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in "
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CertificateVerify - did not match with calculated "
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "hash");
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CHANGE_CIPHER_SPEC;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len)
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 1) {
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received data 0x%x", *pos);
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for record layer");
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = pos + 1 - in_data;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_FINISHED;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_finished(struct tlsv1_server *conn, u8 ct,
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *in_data, size_t *in_len)
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, hlen;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 verify_data[TLS_VERIFY_DATA_LEN];
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Finished",
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) left);
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "type 0x%x", pos[0]);
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos + 1);
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 4;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu > left=%lu)",
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != TLS_VERIFY_DATA_LEN) {
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "in Finished: %lu (expected %d)",
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, TLS_VERIFY_DATA_LEN);
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
11241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
11251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
11261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_client == NULL ||
11271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_client, hash, &hlen)
11281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    < 0) {
11291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_client = NULL;
11321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
11331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
11341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_client = NULL;
11351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
11361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
11371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_client == NULL ||
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_client = NULL;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_client = NULL;
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_client == NULL ||
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_client = NULL;
11591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
11601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
11621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
11631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf(conn->rl.tls_version,
11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    conn->master_secret, TLS_MASTER_SECRET_LEN,
11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "client finished", hash, hlen,
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    verify_data, TLS_VERIFY_DATA_LEN)) {
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			verify_data, TLS_VERIFY_DATA_LEN);
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->use_session_ticket) {
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Abbreviated handshake using session ticket; RFC 4507 */
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed "
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "successfully");
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = ESTABLISHED;
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Full handshake */
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = SERVER_CHANGE_CIPHER_SPEC;
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *buf, size_t *len)
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_ALERT) {
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 2) {
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   buf[0], buf[1]);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 2;
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = FAILED;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_HELLO:
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_hello(conn, ct, buf, len))
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_CERTIFICATE:
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate(conn, ct, buf, len))
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_KEY_EXCHANGE:
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_key_exchange(conn, ct, buf, len))
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CERTIFICATE_VERIFY:
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate_verify(conn, ct, buf, len))
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CHANGE_CIPHER_SPEC:
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_change_cipher_spec(conn, ct, buf, len))
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_FINISHED:
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_finished(conn, ct, buf, len))
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "while processing received message",
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->state);
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_verify_hash_add(&conn->verify, buf, *len);
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1254