tlsv1_server_read.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - read handshake message
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server_i.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *in_data, size_t *in_len)
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *c;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, i, j;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 cipher_suite;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 num_suites;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int compr_null_found;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 ext_type, ext_len;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4)
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ClientHello)", *pos);
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello");
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length */
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left)
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ClientHello */
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len);
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion client_version */
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->client_version = WPA_GET_BE16(pos);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d",
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   conn->client_version >> 8, conn->client_version & 0xff);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->client_version < TLS_VERSION) {
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientHello");
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_PROTOCOL_VERSION);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Random random */
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < TLS_RANDOM_LEN)
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RANDOM_LEN;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->client_random, TLS_RANDOM_LEN);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionID session_id */
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 1 + *pos;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for session resumption */
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CipherSuite cipher_suites<2..2^16-1> */
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = WPA_GET_BE16(pos);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites",
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_suites & 1)
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites /= 2;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cipher_suite = 0;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) {
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = pos;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < num_suites; j++) {
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u16 tmp = WPA_GET_BE16(c);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			c += 2;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!cipher_suite && tmp == conn->cipher_suites[i]) {
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cipher_suite = tmp;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += num_suites * 2;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cipher_suite) {
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite "
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "available");
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->cipher_suite = cipher_suite;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CompressionMethod compression_methods<1..2^8-1> */
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = *pos++;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods",
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	compr_null_found = 0;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_suites; i++) {
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos++ == TLS_COMPRESSION_NULL)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			compr_null_found = 1;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!compr_null_found) {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL "
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "compression");
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos == 1) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the "
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    "end of ClientHello: 0x%02x", *pos);
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos >= 2) {
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Extension client_hello_extension_list<0..2^16-1> */
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ext_len = WPA_GET_BE16(pos);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello "
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "extensions", ext_len);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos != ext_len) {
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello "
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "extension list length %u (expected %u)",
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ext_len, (unsigned int) (end - pos));
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto decode_error;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * struct {
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   ExtensionType extension_type (0..65535)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   opaque extension_data<0..2^16-1>
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * } Extension;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos < end) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_type field");
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_type = WPA_GET_BE16(pos);
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_data length field");
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_len = WPA_GET_BE16(pos);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < ext_len) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Invalid "
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "extension_data field");
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension "
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "type %u", ext_type);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello "
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Extension data", pos, ext_len);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ext_type == TLS_EXT_SESSION_TICKET) {
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(conn->session_ticket);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->session_ticket = os_malloc(ext_len);
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (conn->session_ticket) {
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					os_memcpy(conn->session_ticket, pos,
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  ext_len);
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					conn->session_ticket_len = ext_len;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ext_len;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to "
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "ServerHello");
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_HELLO;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdecode_error:
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello");
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   TLS_ALERT_DECODE_ERROR);
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate(struct tlsv1_server *conn, u8 ct,
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *in_data, size_t *in_len)
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, list_len, cert_len, idx;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *chain = NULL, *last = NULL, *cert;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reason;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu)", (unsigned long) left);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Client did not include "
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Certificate");
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_client_key_exchange(conn, ct, in_data,
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected Certificate/"
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientKeyExchange)", type);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG,
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "TLSv1: Received Certificate (certificate_list len %lu)",
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned long) len);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque ASN.1Cert<2^24-1>;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     ASN.1Cert certificate_list<1..2^24-1>;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } Certificate;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(left=%lu)", (unsigned long) left);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	list_len = WPA_GET_BE24(pos);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((size_t) (end - pos) != list_len) {
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu left=%lu)",
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) list_len,
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) (end - pos));
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = 0;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos < 3) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "certificate_list");
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert_len = WPA_GET_BE24(pos);
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((size_t) (end - pos) < cert_len) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "length (len=%lu left=%lu)",
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) cert_len,
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) idx, (unsigned long) cert_len);
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (idx == 0) {
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_public_key_free(conn->client_rsa_key);
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tls_parse_cert(pos, cert_len,
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   &conn->client_rsa_key)) {
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "the certificate");
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   TLS_ALERT_BAD_CERTIFICATE);
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				x509_certificate_chain_free(chain);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_parse(pos, cert_len);
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "the certificate");
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_BAD_CERTIFICATE);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last == NULL)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			chain = cert;
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			last->next = cert;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = cert;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx++;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert_len;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    &reason) < 0) {
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int tls_reason;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "validation failed (reason=%d)", reason);
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (reason) {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_BAD_CERTIFICATE:
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_REVOKED:
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_EXPIRED:
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNKNOWN_CA:
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNKNOWN_CA;
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		x509_certificate_chain_free(chain);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	x509_certificate_chain_free(chain);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_KEY_EXCHANGE;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange_rsa(
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *out;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t outlen, outbuflen;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 encr_len;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int use_random = 0;
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2) {
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	encr_len = WPA_GET_BE16(pos);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuflen = outlen = end - pos;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ?
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			outlen : TLS_PRE_MASTER_SECRET_LEN);
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out == NULL) {
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   ProtocolVersion client_version;
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   opaque random[46];
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } PreMasterSecret;
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   public-key-encrypted PreMasterSecret pre_master_secret;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } EncryptedPreMasterSecret;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Note: To avoid Bleichenbacher attack, we do not report decryption or
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parsing errors from EncryptedPreMasterSecret processing to the
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * client. Instead, a random pre-master secret is used to force the
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * handshake to fail.
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key,
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 pos, end - pos,
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 out, &outlen) < 0) {
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt "
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "PreMasterSecret (encr_len=%d outlen=%lu)",
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (int) (end - pos), (unsigned long) outlen);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (outlen != TLS_PRE_MASTER_SECRET_LEN) {
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret "
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length %lu", (unsigned long) outlen);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE16(out) != conn->client_version) {
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Client version in "
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientKeyExchange does not match with version in "
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ClientHello");
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (use_random) {
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret "
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to avoid revealing information about private key");
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		outlen = TLS_PRE_MASTER_SECRET_LEN;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_get_random(out, outlen)) {
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "data");
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(out);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, out, outlen);
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(out, 0, outbuflen);
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(out);
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange_dh_anon(
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *dh_yc;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 dh_yc_len;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *shared;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t shared_len;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   select (PublicValueEncoding) {
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case implicit: struct { };
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case explicit: opaque dh_Yc<1..2^16-1>;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   } dh_public;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ClientDiffieHellmanPublic;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic",
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, end - pos);
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == pos) {
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding "
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "not supported");
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value "
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length");
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_yc_len = WPA_GET_BE16(pos);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_yc = pos + 2;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_yc + dh_yc_len > end) {
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow "
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(length %d)", dh_yc_len);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    dh_yc, dh_yc_len);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->dh_secret == NULL) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available");
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	shared_len = conn->cred->dh_p_len;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	shared = os_malloc(shared_len);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (shared == NULL) {
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "DH");
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* shared = Yc^secret mod p */
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret,
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret_len,
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->cred->dh_p, conn->cred->dh_p_len,
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   shared, &shared_len)) {
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(shared);
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			shared, shared_len);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(conn->dh_secret, 0, conn->dh_secret_len);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->dh_secret);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret = NULL;
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, shared, shared_len);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(shared, 0, shared_len);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(shared);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len)
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_key_exchange keyx;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange "
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(Left=%lu)", (unsigned long) left);
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange "
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "length (len=%lu != left=%lu)",
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected ClientKeyExchange)", type);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange");
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = TLS_KEY_X_NULL;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = suite->key_exchange;
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keyx == TLS_KEY_X_DH_anon &&
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0)
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keyx != TLS_KEY_X_DH_anon &&
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_process_client_key_exchange_rsa(conn, pos, end) < 0)
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CERTIFICATE_VERIFY;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *in_data, size_t *in_len)
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t hlen, buflen;
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 slen;
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Client did not include "
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "CertificateVerify");
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_change_cipher_spec(conn, ct, in_data,
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      in_len);
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify "
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message (len=%lu)", (unsigned long) left);
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify "
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message length (len=%lu != left=%lu)",
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) {
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "message %d (expected CertificateVerify)", type);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify");
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   Signature signature;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } CertificateVerify;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hpos = hash;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == SIGN_ALG_RSA) {
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hlen = MD5_MAC_LEN;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify.md5_cert == NULL ||
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0)
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->verify.md5_cert = NULL;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->verify.sha1_cert = NULL;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hpos += MD5_MAC_LEN;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.md5_cert, NULL, NULL);
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_cert = NULL;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_cert == NULL ||
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_cert = NULL;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_cert = NULL;
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alg == SIGN_ALG_RSA)
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hlen += MD5_MAC_LEN;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2) {
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	slen = WPA_GET_BE16(pos);
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < slen) {
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->client_rsa_key == NULL) {
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify "
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "signature");
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buflen = end - pos;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(end - pos);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key,
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    pos, end - pos, buf, &buflen) < 0)
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature");
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature",
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf, buflen);
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) {
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in "
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "CertificateVerify - did not match with calculated "
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "hash");
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CHANGE_CIPHER_SPEC;
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 1) {
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received data 0x%x", *pos);
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for record layer");
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = pos + 1 - in_data;
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_FINISHED;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_finished(struct tlsv1_server *conn, u8 ct,
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *in_data, size_t *in_len)
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, hlen;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 verify_data[TLS_VERIFY_DATA_LEN];
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "received content type 0x%x", ct);
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Finished",
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) left);
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "type 0x%x", pos[0]);
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos + 1);
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 4;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(len=%lu > left=%lu)",
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, (unsigned long) left);
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != TLS_VERIFY_DATA_LEN) {
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "in Finished: %lu (expected %d)",
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) len, TLS_VERIFY_DATA_LEN);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, TLS_VERIFY_DATA_LEN);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_client == NULL ||
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_client = NULL;
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_client = NULL;
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_client == NULL ||
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_client = NULL;
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    verify_data, TLS_VERIFY_DATA_LEN)) {
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			verify_data, TLS_VERIFY_DATA_LEN);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->use_session_ticket) {
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Abbreviated handshake using session ticket; RFC 4507 */
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed "
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "successfully");
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = ESTABLISHED;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Full handshake */
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = SERVER_CHANGE_CIPHER_SPEC;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *buf, size_t *len)
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_ALERT) {
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 2) {
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   buf[0], buf[1]);
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 2;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = FAILED;
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_HELLO:
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_hello(conn, ct, buf, len))
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_CERTIFICATE:
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate(conn, ct, buf, len))
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_KEY_EXCHANGE:
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_key_exchange(conn, ct, buf, len))
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CERTIFICATE_VERIFY:
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate_verify(conn, ct, buf, len))
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CHANGE_CIPHER_SPEC:
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_change_cipher_spec(conn, ct, buf, len))
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_FINISHED:
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_finished(conn, ct, buf, len))
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "while processing received message",
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->state);
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_verify_hash_add(&conn->verify, buf, *len);
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1135