18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - write handshake message
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha256.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server_i.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn)
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = 0;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *cert;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = conn->cred->cert;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cert) {
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += 3 + cert->cert_len;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (x509_certificate_self_signed(cert))
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_get_subject(conn->cred->trusted_certs,
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    &cert->issuer);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return len;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_hello(struct tlsv1_server *conn,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  u8 **msgpos, u8 *end)
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello");
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&now);
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE32(conn->server_random, now.sec);
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "server_random");
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->server_random, TLS_RANDOM_LEN);
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->session_id_len = TLS_SESSION_ID_MAX_LEN;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(conn->session_id, conn->session_id_len)) {
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "session_id");
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    conn->session_id, conn->session_id_len);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerHello */
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion server_version */
851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE16(pos, conn->rl.tls_version);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Random random: uint32 gmt_unix_time, opaque random_bytes */
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN);
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RANDOM_LEN;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SessionID session_id */
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = conn->session_id_len;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, conn->session_id, conn->session_id_len);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->session_id_len;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CipherSuite cipher_suite */
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, conn->cipher_suite);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* CompressionMethod compression_method */
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_COMPRESSION_NULL;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_ticket && conn->session_ticket_cb) {
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = conn->session_ticket_cb(
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->session_ticket_cb_ctx,
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->session_ticket, conn->session_ticket_len,
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->client_random, conn->server_random,
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->master_secret);
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "indicated failure");
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_HANDSHAKE_FAILURE);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->use_session_ticket = res;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->use_session_ticket) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) {
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "derive keys");
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   TLS_ALERT_INTERNAL_ERROR);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RFC 4507 specifies that server would include an empty
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * SessionTicket extension in ServerHello and a
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * NewSessionTicket message after the ServerHello. However,
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * extension at the moment, does not use such extensions.
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * TODO: Add support for configuring RFC 4507 behavior and make
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAP-FAST disable it.
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate(struct tlsv1_server *conn,
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 **msgpos, u8 *end)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *cert;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when "
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "using anonymous DH");
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - Certificate */
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert_start = pos;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = conn->cred->cert;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cert) {
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos + 3 + cert->cert_len > end) {
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for Certificate (cert_len=%lu left=%lu)",
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) cert->cert_len,
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE24(pos, cert->cert_len);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos, cert->cert_start, cert->cert_len);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert->cert_len;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (x509_certificate_self_signed(cert))
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_get_subject(conn->cred->trusted_certs,
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    &cert->issuer);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert == conn->cred->cert || cert == NULL) {
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Server was not configured with all the needed certificates
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to form a full certificate chain. The client may fail to
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * validate the chain unless it is configured with all the
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * missing CA certificates.
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "not configured - validation may fail");
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(cert_start, pos - cert_start - 3);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_key_exchange(struct tlsv1_server *conn,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 u8 **msgpos, u8 *end)
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_key_exchange keyx;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *dh_ys;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t dh_ys_len;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = TLS_KEY_X_NULL;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = suite->key_exchange;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed");
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keyx != TLS_KEY_X_DH_anon) {
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO? */
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet "
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "supported with key exchange type %d", keyx);
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->cred->dh_g == NULL) {
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for "
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ServerKeyExhcange");
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->dh_secret);
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret_len = conn->cred->dh_p_len;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret = os_malloc(conn->dh_secret_len);
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_secret == NULL) {
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "memory for secret (Diffie-Hellman)");
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data for Diffie-Hellman");
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn->dh_secret);
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret = NULL;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) >
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0)
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret[0] = 0; /* make sure secret < p */
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = conn->dh_secret;
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0)
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos != conn->dh_secret) {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memmove(conn->dh_secret, pos,
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret_len - (pos - conn->dh_secret));
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret_len -= pos - conn->dh_secret;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value",
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->dh_secret, conn->dh_secret_len);
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Ys = g^secret mod p */
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_ys_len = conn->cred->dh_p_len;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_ys = os_malloc(dh_ys_len);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_ys == NULL) {
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for "
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Diffie-Hellman");
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret, conn->dh_secret_len,
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->cred->dh_p, conn->cred->dh_p_len,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   dh_ys, &dh_ys_len)) {
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    dh_ys, dh_ys_len);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    select (KeyExchangeAlgorithm) {
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *       case diffie_hellman:
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          ServerDHParams params;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          Signature signed_params;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *       case rsa:
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          ServerRSAParams params;
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          Signature signed_params;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    };
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ServerKeyExchange;
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_p<1..2^16-1>;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_g<1..2^16-1>;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_Ys<1..2^16-1>;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ServerDHParams;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange");
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerDHParams */
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_p */
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos + 2 + conn->cred->dh_p_len > end) {
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_p");
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, conn->cred->dh_p_len);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len);
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->cred->dh_p_len;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_g */
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos + 2 + conn->cred->dh_g_len > end) {
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_g");
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, conn->cred->dh_g_len);
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->cred->dh_g_len;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_Ys */
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos + 2 + dh_ys_len > end) {
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_Ys");
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, dh_ys_len);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, dh_ys, dh_ys_len);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += dh_ys_len;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dh_ys);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate_request(struct tlsv1_server *conn,
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						u8 **msgpos, u8 *end)
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->verify_peer) {
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed");
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest");
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST;
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - CertificateRequest */
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * enum {
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   (255)
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ClientCertificateType;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * ClientCertificateType certificate_types<1..2^8-1>
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 1;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 1; /* rsa_sign */
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque DistinguishedName<1..2^16-1>
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * DistinguishedName certificate_authorities<3..2^16-1>
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for listing DNs for trusted CAs */
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, 0);
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_hello_done(struct tlsv1_server *conn,
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       u8 **msgpos, u8 *end)
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *pos;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 payload[4];
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone");
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = payload;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE;
5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* uint24 length */
5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE24(pos, 0);
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerHelloDone (empty) */
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, payload, pos - payload,
5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tls_verify_hash_add(&conn->verify, payload, pos - payload);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u8 **msgpos, u8 *end)
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 payload[1];
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	payload[0] = TLS_CHANGE_CIPHER_SPEC;
5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, payload, sizeof(payload),
5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_finished(struct tlsv1_server *conn,
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     u8 **msgpos, u8 *end)
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *pos, *hs_start;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen, hlen;
5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN];
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Encrypted Handshake Message: Finished */
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_server == NULL ||
5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    < 0) {
5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_server = NULL;
5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_server = NULL;
5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_server == NULL ||
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_server = NULL;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_server = NULL;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_server == NULL ||
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_server = NULL;
6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf(conn->rl.tls_version,
6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    conn->master_secret, TLS_MASTER_SECRET_LEN,
6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "server finished", hash, hlen,
6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) {
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			verify_data + 1 + 3, TLS_VERIFY_DATA_LEN);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = hs_start = verify_data;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* uint24 length */
6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN);
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_VERIFY_DATA_LEN;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, hs_start, pos - hs_start,
6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *msg, *end, *pos;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t msglen;
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msglen = 1000 + tls_server_cert_chain_der_len(conn);
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(msglen);
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = msg + msglen;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_hello(conn, &pos, end) < 0) {
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->use_session_ticket) {
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Abbreviated handshake using session ticket; RFC 4507 */
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tls_write_server_finished(conn, &pos, end) < 0) {
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(msg);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*out_len = pos - msg;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = CHANGE_CIPHER_SPEC;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return msg;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Full handshake */
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_certificate(conn, &pos, end) < 0 ||
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_key_exchange(conn, &pos, end) < 0 ||
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_certificate_request(conn, &pos, end) < 0 ||
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_hello_done(conn, &pos, end) < 0) {
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - msg;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_CERTIFICATE;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn,
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					size_t *out_len)
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *msg, *end, *pos;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(1000);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = msg + 1000;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_finished(conn, &pos, end) < 0) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - msg;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully");
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = ESTABLISHED;
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len)
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_HELLO:
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_send_server_hello(conn, out_len);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_CHANGE_CIPHER_SPEC:
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_send_change_cipher_spec(conn, out_len);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->state == ESTABLISHED && conn->use_session_ticket) {
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Abbreviated handshake was already completed. */
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "generating reply", conn->state);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     u8 description, size_t *out_len)
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *alert, *pos, *length;
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	alert = os_malloc(10);
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alert == NULL)
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = alert;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TLSPlaintext */
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ContentType type */
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_CONTENT_TYPE_ALERT;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion version */
7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		     TLS_VERSION);
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint16 length (to be filled) */
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	length = pos;
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Alert */
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AlertLevel level */
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = level;
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AlertDescription description */
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = description;
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(length, pos - length - 2);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - alert;
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return alert;
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
802