18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - read handshake message
3818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha256.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server_i.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len);
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len);
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidtstatic int testing_cipher_suite_filter(struct tlsv1_server *conn, u16 suite)
31818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt{
32818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
33818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if ((conn->test_flags &
34b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	     (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE |
35b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	      TLS_DHE_PRIME_511B | TLS_DHE_PRIME_767B | TLS_DHE_PRIME_15 |
36b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	      TLS_DHE_PRIME_58B | TLS_DHE_NON_PRIME)) &&
37818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 &&
38818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA &&
39818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 &&
40818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA &&
41818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    suite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
42818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		return 1;
43818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
44818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
45818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	return 0;
46818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt}
47818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
48818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
49d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidtstatic void tls_process_status_request_item(struct tlsv1_server *conn,
50d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					    const u8 *req, size_t req_len)
51d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt{
52d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	const u8 *pos, *end;
53d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	u8 status_type;
54d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
55d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos = req;
56d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	end = req + req_len;
57d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
58d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/*
59d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * RFC 6961, 2.2:
60d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * struct {
61d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   CertificateStatusType status_type;
62d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   uint16 request_length;
63d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   select (status_type) {
64d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *     case ocsp: OCSPStatusRequest;
65d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *     case ocsp_multi: OCSPStatusRequest;
66d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   } request;
67d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * } CertificateStatusRequestItemV2;
68d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *
69d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
70d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 */
71d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
72d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (end - pos < 1)
73d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		return; /* Truncated data */
74d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
75d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	status_type = *pos++;
76d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatusType %u", status_type);
77d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (status_type != 1 && status_type != 2)
78d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		return; /* Unsupported status type */
79d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/*
80d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * For now, only OCSP stapling is supported, so ignore the specific
81d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * request, if any.
82d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 */
83d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: OCSPStatusRequest", pos, end - pos);
84d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
85d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (status_type == 2)
86d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		conn->status_request_multi = 1;
87d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt}
88d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
89d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
90d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidtstatic void tls_process_status_request_v2(struct tlsv1_server *conn,
91d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					  const u8 *ext, size_t ext_len)
92d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt{
93d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	const u8 *pos, *end;
94d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
95d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	conn->status_request_v2 = 1;
96d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
97d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos = ext;
98d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	end = ext + ext_len;
99d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
100d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/*
101d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * RFC 6961, 2.2:
102d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * struct {
103d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   CertificateStatusRequestItemV2
104d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *                    certificate_status_req_list<1..2^16-1>;
105d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * } CertificateStatusRequestListV2;
106d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 */
107d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
108d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	while (end - pos >= 2) {
109d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		u16 len;
110d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
111d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		len = WPA_GET_BE16(pos);
112d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += 2;
113d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		if (len > end - pos)
114d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			break; /* Truncated data */
115d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		tls_process_status_request_item(conn, pos, len);
116d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += len;
117d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
118d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt}
119d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
120d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    const u8 *in_data, size_t *in_len)
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *c;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, i, j;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 cipher_suite;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 num_suites;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int compr_null_found;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 ext_type, ext_len;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
133818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
147818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientHello)",
148818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 *pos);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
153818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received ClientHello");
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length */
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left)
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ClientHello */
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion client_version */
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->client_version = WPA_GET_BE16(pos);
172818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Client version %d.%d",
173818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 conn->client_version >> 8,
174818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 conn->client_version & 0xff);
1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->client_version < TLS_VERSION_1) {
176818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected protocol version in ClientHello %u.%u",
177818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 conn->client_version >> 8,
178818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 conn->client_version & 0xff);
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_PROTOCOL_VERSION);
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (TLS_VERSION == TLS_VERSION_1)
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1;
1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (conn->client_version >= TLS_VERSION_1_2)
1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1_2;
1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else if (conn->client_version > TLS_VERSION_1_1)
1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = TLS_VERSION_1_1;
1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->rl.tls_version = conn->client_version;
195818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Using TLS v%s",
196818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 tls_version_str(conn->rl.tls_version));
1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Random random */
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < TLS_RANDOM_LEN)
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RANDOM_LEN;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->client_random, TLS_RANDOM_LEN);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionID session_id */
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 1 + *pos;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for session resumption */
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CipherSuite cipher_suites<2..2^16-1> */
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = WPA_GET_BE16(pos);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites",
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num_suites & 1)
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites /= 2;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cipher_suite = 0;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) {
231818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (testing_cipher_suite_filter(conn, conn->cipher_suites[i]))
232818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			continue;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = pos;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < num_suites; j++) {
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u16 tmp = WPA_GET_BE16(c);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			c += 2;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!cipher_suite && tmp == conn->cipher_suites[i]) {
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				cipher_suite = tmp;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += num_suites * 2;
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!cipher_suite) {
245818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "No supported cipher suite available");
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->cipher_suite = cipher_suite;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CompressionMethod compression_methods<1..2^8-1> */
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 1)
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num_suites = *pos++;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < num_suites)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods",
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, num_suites);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	compr_null_found = 0;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_suites; i++) {
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*pos++ == TLS_COMPRESSION_NULL)
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			compr_null_found = 1;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!compr_null_found) {
275818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Client does not accept NULL compression");
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_ILLEGAL_PARAMETER);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos == 1) {
282818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected extra octet in the end of ClientHello: 0x%02x",
283818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 *pos);
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto decode_error;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos >= 2) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Extension client_hello_extension_list<0..2^16-1> */
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ext_len = WPA_GET_BE16(pos);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 2;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
292818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "%u bytes of ClientHello extensions",
293818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ext_len);
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos != ext_len) {
295818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Invalid ClientHello extension list length %u (expected %u)",
296818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 ext_len, (unsigned int) (end - pos));
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto decode_error;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * struct {
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   ExtensionType extension_type (0..65535)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *   opaque extension_data<0..2^16-1>
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * } Extension;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos < end) {
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
309818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				tlsv1_server_log(conn, "Invalid extension_type field");
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_type = WPA_GET_BE16(pos);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < 2) {
317818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				tlsv1_server_log(conn, "Invalid extension_data length field");
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ext_len = WPA_GET_BE16(pos);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (end - pos < ext_len) {
325818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				tlsv1_server_log(conn, "Invalid extension_data field");
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto decode_error;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
329818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "ClientHello Extension type %u",
330818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 ext_type);
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello "
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Extension data", pos, ext_len);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ext_type == TLS_EXT_SESSION_TICKET) {
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_free(conn->session_ticket);
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				conn->session_ticket = os_malloc(ext_len);
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (conn->session_ticket) {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					os_memcpy(conn->session_ticket, pos,
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  ext_len);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					conn->session_ticket_len = ext_len;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				}
342d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			} else if (ext_type == TLS_EXT_STATUS_REQUEST) {
343d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				conn->status_request = 1;
344d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			} else if (ext_type == TLS_EXT_STATUS_REQUEST_V2) {
345d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				tls_process_status_request_v2(conn, pos,
346d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt							      ext_len);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += ext_len;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
355818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "ClientHello OK - proceed to ServerHello");
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = SERVER_HELLO;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdecode_error:
361818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Failed to decode ClientHello");
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   TLS_ALERT_DECODE_ERROR);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate(struct tlsv1_server *conn, u8 ct,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *in_data, size_t *in_len)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, list_len, cert_len, idx;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *chain = NULL, *last = NULL, *cert;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reason;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
378818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
379818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
389818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short Certificate message (len=%lu)",
390818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) left);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
402818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected Certificate message length (len=%lu != left=%lu)",
403818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) len, (unsigned long) left);
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
411818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Client did not include Certificate");
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_client_key_exchange(conn, ct, in_data,
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						       in_len);
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
421818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected Certificate/ClientKeyExchange)",
422818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 type);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received Certificate (certificate_list len %lu)",
429818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 (unsigned long) len);
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque ASN.1Cert<2^24-1>;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     ASN.1Cert certificate_list<1..2^24-1>;
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } Certificate;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
442818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short Certificate (left=%lu)",
443818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) left);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	list_len = WPA_GET_BE24(pos);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((size_t) (end - pos) != list_len) {
453818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected certificate_list length (len=%lu left=%lu)",
454818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) list_len,
455818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) (end - pos));
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	idx = 0;
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos < end) {
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (end - pos < 3) {
464818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Failed to parse certificate_list");
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert_len = WPA_GET_BE24(pos);
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((size_t) (end - pos) < cert_len) {
475818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Unexpected certificate length (len=%lu left=%lu)",
476818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 (unsigned long) cert_len,
477818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					 (unsigned long) (end - pos));
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
484818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Certificate %lu (len %lu)",
485818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) idx, (unsigned long) cert_len);
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (idx == 0) {
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			crypto_public_key_free(conn->client_rsa_key);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tls_parse_cert(pos, cert_len,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   &conn->client_rsa_key)) {
491818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				tlsv1_server_log(conn, "Failed to parse the certificate");
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   TLS_ALERT_BAD_CERTIFICATE);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				x509_certificate_chain_free(chain);
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_parse(pos, cert_len);
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cert == NULL) {
501818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Failed to parse the certificate");
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_BAD_CERTIFICATE);
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			x509_certificate_chain_free(chain);
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last == NULL)
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			chain = cert;
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			last->next = cert;
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = cert;
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		idx++;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert_len;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
519c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					    &reason, 0) < 0) {
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int tls_reason;
521818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Server certificate chain validation failed (reason=%d)",
522818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 reason);
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (reason) {
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_BAD_CERTIFICATE:
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_REVOKED:
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_EXPIRED:
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_CERTIFICATE_UNKNOWN:
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case X509_VALIDATE_UNKNOWN_CA:
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_UNKNOWN_CA;
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tls_reason = TLS_ALERT_BAD_CERTIFICATE;
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		x509_certificate_chain_free(chain);
548d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		return -1;
549d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	}
550d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt
551d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	if (chain && (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
552d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	    !(chain->ext_key_usage &
553d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt	      (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_CLIENT_AUTH))) {
554d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
555d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				   TLS_ALERT_BAD_CERTIFICATE);
556d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt		x509_certificate_chain_free(chain);
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	x509_certificate_chain_free(chain);
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_KEY_EXCHANGE;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange_rsa(
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *out;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t outlen, outbuflen;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 encr_len;
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int use_random = 0;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 2) {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	encr_len = WPA_GET_BE16(pos);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (pos + encr_len > end) {
588818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Invalid ClientKeyExchange format: encr_len=%u left=%u",
589818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 encr_len, (unsigned int) (end - pos));
5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	outbuflen = outlen = end - pos;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ?
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			outlen : TLS_PRE_MASTER_SECRET_LEN);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (out == NULL) {
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   ProtocolVersion client_version;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   opaque random[46];
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } PreMasterSecret;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   public-key-encrypted PreMasterSecret pre_master_secret;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } EncryptedPreMasterSecret;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Note: To avoid Bleichenbacher attack, we do not report decryption or
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * parsing errors from EncryptedPreMasterSecret processing to the
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * client. Instead, a random pre-master secret is used to force the
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * handshake to fail.
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key,
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						 pos, encr_len,
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 out, &outlen) < 0) {
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt "
6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "PreMasterSecret (encr_len=%u outlen=%lu)",
6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   encr_len, (unsigned long) outlen);
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) {
632818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected PreMasterSecret length %lu",
633818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) outlen);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!use_random && WPA_GET_BE16(out) != conn->client_version) {
638818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Client version in ClientKeyExchange does not match with version in ClientHello");
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		use_random = 1;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (use_random) {
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret "
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "to avoid revealing information about private key");
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		outlen = TLS_PRE_MASTER_SECRET_LEN;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_get_random(out, outlen)) {
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "data");
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(out);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, out, outlen);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(out, 0, outbuflen);
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(out);
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
673818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidtstatic int tls_process_client_key_exchange_dh(
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *dh_yc;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 dh_yc_len;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *shared;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t shared_len;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
681b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	const u8 *dh_p;
682b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	size_t dh_p_len;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   select (PublicValueEncoding) {
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case implicit: struct { };
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *     case explicit: opaque dh_Yc<1..2^16-1>;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   } dh_public;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ClientDiffieHellmanPublic;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
693818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "ClientDiffieHellmanPublic received");
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic",
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, end - pos);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end == pos) {
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding "
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "not supported");
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (end - pos < 3) {
706818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Invalid client public value length");
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	dh_yc_len = WPA_GET_BE16(pos);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_yc = pos + 2;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (dh_yc_len > end - dh_yc) {
716818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Client public value overflow (length %d)",
717818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 dh_yc_len);
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    dh_yc, dh_yc_len);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->dh_secret == NULL) {
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available");
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
734b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len);
735b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
736b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	shared_len = dh_p_len;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	shared = os_malloc(shared_len);
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (shared == NULL) {
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "DH");
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* shared = Yc^secret mod p */
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret,
748b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt			   conn->dh_secret_len, dh_p, dh_p_len,
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   shared, &shared_len)) {
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(shared);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			shared, shared_len);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(conn->dh_secret, 0, conn->dh_secret_len);
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->dh_secret);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret = NULL;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = tlsv1_server_derive_keys(conn, shared, shared_len);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Clear the pre-master secret since it is not needed anymore */
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(shared, 0, shared_len);
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(shared);
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res) {
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct,
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in_data, size_t *in_len)
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_key_exchange keyx;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
789818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
790818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
800818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short ClientKeyExchange (Left=%lu)",
801818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) left);
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
813818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Mismatch in ClientKeyExchange length (len=%lu != left=%lu)",
814818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) len, (unsigned long) left);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) {
823818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientKeyExchange)",
824818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 type);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
830818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received ClientKeyExchange");
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len);
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = TLS_KEY_X_NULL;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = suite->key_exchange;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
840818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if ((keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) &&
841818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    tls_process_client_key_exchange_dh(conn, pos, end) < 0)
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
844818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA &&
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_process_client_key_exchange_rsa(conn, pos, end) < 0)
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CERTIFICATE_VERIFY;
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *in_data, size_t *in_len)
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len;
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
862818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	size_t hlen;
863818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
864818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	u8 alert;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->verify_peer) {
868818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Client did not include CertificateVerify");
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_UNEXPECTED_MESSAGE);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_process_change_cipher_spec(conn, ct, in_data,
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      in_len);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
879818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x",
880818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
890818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short CertificateVerify message (len=%lu)",
891818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) left);
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	type = *pos++;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
903818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected CertificateVerify message length (len=%lu != left=%lu)",
904818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) len, (unsigned long) left);
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) {
913818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Received unexpected handshake message %d (expected CertificateVerify)",
914818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 type);
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
920818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received CertificateVerify");
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   Signature signature;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } CertificateVerify;
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hpos = hash;
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version == TLS_VERSION_1_2) {
9321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
9331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * RFC 5246, 4.7:
9341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * TLS v1.2 adds explicit indication of the used signature and
9351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * hash algorithms.
9361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *
9371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * struct {
9381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   HashAlgorithm hash;
9391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 *   SignatureAlgorithm signature;
9401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * } SignatureAndHashAlgorithm;
9411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
9421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (end - pos < 2) {
9431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
9451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
9461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (pos[0] != TLS_HASH_ALG_SHA256 ||
9481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    pos[1] != TLS_SIGN_ALG_RSA) {
9491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/"
9501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   "signature(%u) algorithm",
9511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   pos[0], pos[1]);
9521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
9541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
9551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		pos += 2;
9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_cert == NULL ||
9601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
9611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    0) {
9621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_cert = NULL;
9631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
9651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_cert = NULL;
9681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
9691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
971203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	hlen = MD5_MAC_LEN;
972203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	if (conn->verify.md5_cert == NULL ||
973203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	    crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
974203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
975203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
976203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		conn->verify.md5_cert = NULL;
977203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
978203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		conn->verify.sha1_cert = NULL;
979203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt		return -1;
980203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	}
981203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	hpos += MD5_MAC_LEN;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_cert = NULL;
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_cert == NULL ||
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_cert = NULL;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_cert = NULL;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
994203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt	hlen += MD5_MAC_LEN;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
9971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
9981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
9991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1002818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (tls_verify_signature(conn->rl.tls_version, conn->client_rsa_key,
1003818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 hash, hlen, pos, end - pos, &alert) < 0) {
1004818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Invalid Signature in CertificateVerify");
1005818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CHANGE_CIPHER_SPEC;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_change_cipher_spec(struct tlsv1_server *conn,
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u8 ct, const u8 *in_data,
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  size_t *in_len)
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
1025818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected ChangeCipherSpec; received content type 0x%x",
1026818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 1) {
1036818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short ChangeCipherSpec");
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*pos != TLS_CHANGE_CIPHER_SPEC) {
1043818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected ChangeCipherSpec; received data 0x%x",
1044818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 *pos);
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1050818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received ChangeCipherSpec");
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "for record layer");
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = pos + 1 - in_data;
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_FINISHED;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_process_client_finished(struct tlsv1_server *conn, u8 ct,
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *in_data, size_t *in_len)
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left, len, hlen;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 verify_data[TLS_VERIFY_DATA_LEN];
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1075818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
1076818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if ((conn->test_flags &
1077818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	     (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) &&
1078818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	    !conn->test_failure_reported) {
1079818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after invalid ServerKeyExchange");
1080818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		conn->test_failure_reported = 1;
1081818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	}
1082b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
1083b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if ((conn->test_flags & TLS_DHE_PRIME_15) &&
1084b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    !conn->test_failure_reported) {
1085b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after bogus DHE \"prime\" 15");
1086b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		conn->test_failure_reported = 1;
1087b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
1088b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
1089b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if ((conn->test_flags & TLS_DHE_PRIME_58B) &&
1090b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    !conn->test_failure_reported) {
1091b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after short 58-bit DHE prime in long container");
1092b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		conn->test_failure_reported = 1;
1093b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
1094b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
1095b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if ((conn->test_flags & TLS_DHE_PRIME_511B) &&
1096b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    !conn->test_failure_reported) {
1097b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tlsv1_server_log(conn, "TEST-WARNING: Client Finished received after short 511-bit DHE prime (insecure)");
1098b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		conn->test_failure_reported = 1;
1099b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
1100b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
1101b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if ((conn->test_flags & TLS_DHE_PRIME_767B) &&
1102b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    !conn->test_failure_reported) {
1103b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after 767-bit DHE prime (relatively insecure)");
1104b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		conn->test_failure_reported = 1;
1105b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
1106b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
1107b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if ((conn->test_flags & TLS_DHE_NON_PRIME) &&
1108b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    !conn->test_failure_reported) {
1109b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after non-prime claimed as DHE prime");
1110b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		conn->test_failure_reported = 1;
1111b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	}
1112818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
1113818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
1115818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Expected Finished; received content type 0x%x",
1116818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 ct);
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = in_data;
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = *in_len;
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (left < 4) {
1126818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short record (left=%lu) forFinished",
1127818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) left);
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "type 0x%x", pos[0]);
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_UNEXPECTED_MESSAGE);
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE24(pos + 1);
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 4;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left -= 4;
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > left) {
1147818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Too short buffer for Finished (len=%lu > left=%lu)",
1148818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) len, (unsigned long) left);
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = pos + len;
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len != TLS_VERIFY_DATA_LEN) {
1155818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected verify_data length in Finished: %lu (expected %d)",
1156818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 (unsigned long) len, TLS_VERIFY_DATA_LEN);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECODE_ERROR);
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    pos, TLS_VERIFY_DATA_LEN);
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
11651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
11661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
11671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_client == NULL ||
11681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_client, hash, &hlen)
11691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    < 0) {
11701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
11721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_client = NULL;
11731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
11741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
11751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_client = NULL;
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
11781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_client == NULL ||
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_client = NULL;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_client = NULL;
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_client == NULL ||
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_client = NULL;
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_client = NULL;
12001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
12011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
12031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
12041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf(conn->rl.tls_version,
12071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    conn->master_secret, TLS_MASTER_SECRET_LEN,
12081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "client finished", hash, hlen,
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    verify_data, TLS_VERIFY_DATA_LEN)) {
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_DECRYPT_ERROR);
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			verify_data, TLS_VERIFY_DATA_LEN);
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
1219818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Mismatch in verify_data");
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1223818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Received Finished");
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*in_len = end - in_data;
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->use_session_ticket) {
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Abbreviated handshake using session ticket; RFC 4507 */
1229818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Abbreviated handshake completed successfully");
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = ESTABLISHED;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Full handshake */
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = SERVER_CHANGE_CIPHER_SPEC;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct,
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *buf, size_t *len)
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_ALERT) {
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (*len < 2) {
1245818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "Alert underflow");
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_DECODE_ERROR);
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1250818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Received alert %d:%d", buf[0], buf[1]);
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*len = 2;
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = FAILED;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_HELLO:
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_hello(conn, ct, buf, len))
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_CERTIFICATE:
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate(conn, ct, buf, len))
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_KEY_EXCHANGE:
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_key_exchange(conn, ct, buf, len))
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CERTIFICATE_VERIFY:
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_certificate_verify(conn, ct, buf, len))
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CHANGE_CIPHER_SPEC:
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_change_cipher_spec(conn, ct, buf, len))
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case CLIENT_FINISHED:
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_process_client_finished(conn, ct, buf, len))
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1282818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected state %d while processing received message",
1283818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 conn->state);
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tls_verify_hash_add(&conn->verify, buf, *len);
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1292