18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - write 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 "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{
45d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time now;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
51818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "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
100d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* Extension */
101d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	ext_start = pos;
102d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos += 2;
103d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
104d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (conn->status_request) {
105d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/* Add a status_request extension with empty extension_data */
106d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/* ExtensionsType extension_type = status_request(5) */
107d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
108d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += 2;
109d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/* opaque extension_data<0..2^16-1> length */
110d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		WPA_PUT_BE16(pos, 0);
111d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += 2;
112d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
113d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
114d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (conn->status_request_v2) {
115d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/*
116d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		  Add a status_request_v2 extension with empty extension_data
117d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		*/
118d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/* ExtensionsType extension_type = status_request_v2(17) */
119d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
120d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += 2;
121d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		/* opaque extension_data<0..2^16-1> length */
122d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		WPA_PUT_BE16(pos, 0);
123d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos += 2;
124d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
125d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->session_ticket && conn->session_ticket_cb) {
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = conn->session_ticket_cb(
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->session_ticket_cb_ctx,
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->session_ticket, conn->session_ticket_len,
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->client_random, conn->server_random,
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->master_secret);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
133818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "SessionTicket callback indicated failure");
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_HANDSHAKE_FAILURE);
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->use_session_ticket = res;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->use_session_ticket) {
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) {
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "derive keys");
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   TLS_ALERT_INTERNAL_ERROR);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RFC 4507 specifies that server would include an empty
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * SessionTicket extension in ServerHello and a
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * NewSessionTicket message after the ServerHello. However,
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * extension at the moment, does not use such extensions.
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 *
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * TODO: Add support for configuring RFC 4507 behavior and make
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * EAP-FAST disable it.
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
162d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (pos == ext_start + 2)
163d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		pos -= 2; /* no extensions */
164d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	else
165d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		WPA_PUT_BE16(ext_start, pos - ext_start - 2);
166d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate(struct tlsv1_server *conn,
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					u8 **msgpos, u8 *end)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct x509_certificate *cert;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when "
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "using anonymous DH");
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
202d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
203d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
204d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
205d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
206d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send Certificate");
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - Certificate */
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert_start = pos;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cert = conn->cred->cert;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cert) {
227d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (3 + cert->cert_len > (size_t) (end - pos)) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for Certificate (cert_len=%lu left=%lu)",
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) cert->cert_len,
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   (unsigned long) (end - pos));
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE24(pos, cert->cert_len);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 3;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos, cert->cert_start, cert->cert_len);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += cert->cert_len;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (x509_certificate_self_signed(cert))
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cert = x509_certificate_get_subject(conn->cred->trusted_certs,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    &cert->issuer);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cert == conn->cred->cert || cert == NULL) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Server was not configured with all the needed certificates
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to form a full certificate chain. The client may fail to
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * validate the chain unless it is configured with all the
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * missing CA certificates.
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain "
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "not configured - validation may fail");
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(cert_start, pos - cert_start - 3);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidtstatic int tls_write_server_certificate_status(struct tlsv1_server *conn,
279d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					       u8 **msgpos, u8 *end,
280d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					       int ocsp_multi,
281d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					       char *ocsp_resp,
282d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					       size_t ocsp_resp_len)
283d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt{
284d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length;
285d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	size_t rlen;
286d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
287d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (!ocsp_resp) {
288d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		 /*
289d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		  * Client did not request certificate status or there is no
290d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		  * matching response cached.
291d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		  */
292d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		return 0;
293d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
294d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
295d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos = *msgpos;
296d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + ocsp_resp_len >
297d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	    (unsigned int) (end - pos)) {
298d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
299d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
300d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		return -1;
301d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
302d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
303d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	tlsv1_server_log(conn, "Send CertificateStatus (multi=%d)", ocsp_multi);
304d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	rhdr = pos;
305d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
306d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
307d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
308d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
309d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* Handshake */
310d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	hs_start = pos;
311d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* HandshakeType msg_type */
312d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS;
313d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* uint24 length (to be filled) */
314d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	hs_length = pos;
315d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos += 3;
316d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
317d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* body - CertificateStatus
318d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *
319d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * struct {
320d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *     CertificateStatusType status_type;
321d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *     select (status_type) {
322d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *         case ocsp: OCSPResponse;
323d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *         case ocsp_multi: OCSPResponseList;
324d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *     } response;
325d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * } CertificateStatus;
326d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *
327d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * opaque OCSPResponse<1..2^24-1>;
328d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *
329d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * struct {
330d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 *   OCSPResponse ocsp_response_list<1..2^24-1>;
331d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 * } OCSPResponseList;
332d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	 */
333d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
334d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* CertificateStatusType status_type */
335d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (ocsp_multi)
336d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		*pos++ = 2; /* ocsp_multi(2) */
337d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	else
338d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		*pos++ = 1; /* ocsp(1) */
339d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	/* uint24 length of OCSPResponse */
340d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	WPA_PUT_BE24(pos, ocsp_resp_len);
341d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos += 3;
342d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	os_memcpy(pos, ocsp_resp, ocsp_resp_len);
343d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos += ocsp_resp_len;
344d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
345d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
346d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
347d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
348d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
349d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			      &rlen) < 0) {
350d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
351d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
352d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
353d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		return -1;
354d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
355d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	pos = rhdr + rlen;
356d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
357d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
358d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
359d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	*msgpos = pos;
360d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
361d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	return 0;
362d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt}
363d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
364d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_key_exchange(struct tlsv1_server *conn,
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 u8 **msgpos, u8 *end)
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_key_exchange keyx;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct tls_cipher_suite *suite;
370818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length, *server_params;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *dh_ys;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t dh_ys_len;
374b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	const u8 *dh_p;
375b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	size_t dh_p_len;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (suite == NULL)
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = TLS_KEY_X_NULL;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyx = suite->key_exchange;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed");
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA) {
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet "
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "supported with key exchange type %d", keyx);
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    conn->cred->dh_g == NULL) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for "
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ServerKeyExhcange");
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
401b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len);
402b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(conn->dh_secret);
404b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	conn->dh_secret_len = dh_p_len;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->dh_secret = os_malloc(conn->dh_secret_len);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->dh_secret == NULL) {
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "memory for secret (Diffie-Hellman)");
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "data for Diffie-Hellman");
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(conn->dh_secret);
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret = NULL;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
423b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (os_memcmp(conn->dh_secret, dh_p, conn->dh_secret_len) > 0)
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret[0] = 0; /* make sure secret < p */
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = conn->dh_secret;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0)
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos != conn->dh_secret) {
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memmove(conn->dh_secret, pos,
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret_len - (pos - conn->dh_secret));
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->dh_secret_len -= pos - conn->dh_secret;
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value",
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conn->dh_secret, conn->dh_secret_len);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Ys = g^secret mod p */
438b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	dh_ys_len = dh_p_len;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dh_ys = os_malloc(dh_ys_len);
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dh_ys == NULL) {
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for "
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Diffie-Hellman");
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   conn->dh_secret, conn->dh_secret_len,
449b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt			   dh_p, dh_p_len, dh_ys, &dh_ys_len)) {
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    dh_ys, dh_ys_len);
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    select (KeyExchangeAlgorithm) {
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *       case diffie_hellman:
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          ServerDHParams params;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          Signature signed_params;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *       case rsa:
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          ServerRSAParams params;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *          Signature signed_params;
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    };
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ServerKeyExchange;
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * struct {
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_p<1..2^16-1>;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_g<1..2^16-1>;
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *    opaque dh_Ys<1..2^16-1>;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ServerDHParams;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
480818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send ServerKeyExchange");
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE;
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerDHParams */
495818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	server_params = pos;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_p */
497d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (2 + dh_p_len > (size_t) (end - pos)) {
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_p");
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
505b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	WPA_PUT_BE16(pos, dh_p_len);
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
507b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	os_memcpy(pos, dh_p, dh_p_len);
508b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	pos += dh_p_len;
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_g */
511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (2 + conn->cred->dh_g_len > (size_t) (end - pos)) {
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_g");
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, conn->cred->dh_g_len);
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += conn->cred->dh_g_len;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* dh_Ys */
525d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (2 + dh_ys_len > (size_t) (end - pos)) {
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "dh_Ys");
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dh_ys);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, dh_ys_len);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, dh_ys, dh_ys_len);
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += dh_ys_len;
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dh_ys);
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
539818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	/*
540818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 * select (SignatureAlgorithm)
541818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 * {   case anonymous: struct { };
542818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *     case rsa:
543818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *         digitally-signed struct {
544818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *             opaque md5_hash[16];
545818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *             opaque sha_hash[20];
546818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *         };
547818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *     case dsa:
548818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *         digitally-signed struct {
549818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *             opaque sha_hash[20];
550818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *         };
551818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 * } Signature;
552818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *
553818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 * md5_hash
554818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *     MD5(ClientHello.random + ServerHello.random + ServerParams);
555818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *
556818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 * sha_hash
557818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 *     SHA(ClientHello.random + ServerHello.random + ServerParams);
558818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	 */
559818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
560818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (keyx == TLS_KEY_X_DHE_RSA) {
561818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		u8 hash[100];
562818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		u8 *signed_start;
563818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		size_t clen;
564818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		int hlen;
565818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
566818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (conn->rl.tls_version >= TLS_VERSION_1_2) {
567818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TLSV12
568818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hlen = tlsv12_key_x_server_params_hash(
569d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				conn->rl.tls_version, TLS_HASH_ALG_SHA256,
570d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt				conn->client_random,
571818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->server_random, server_params,
572818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				pos - server_params, hash + 19);
573818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
574818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			/*
575818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * RFC 5246, 4.7:
576818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * TLS v1.2 adds explicit indication of the used
577818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * signature and hash algorithms.
578818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *
579818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * struct {
580818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   HashAlgorithm hash;
581818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   SignatureAlgorithm signature;
582818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * } SignatureAndHashAlgorithm;
583818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 */
584d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			if (hlen < 0 || end - pos < 2) {
585818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
586818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt						   TLS_ALERT_INTERNAL_ERROR);
587818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				return -1;
588818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			}
589818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			*pos++ = TLS_HASH_ALG_SHA256;
590818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			*pos++ = TLS_SIGN_ALG_RSA;
591818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
592818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			/*
593818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
594818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *
595818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * DigestInfo ::= SEQUENCE {
596818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   digestAlgorithm DigestAlgorithm,
597818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *   digest OCTET STRING
598818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * }
599818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *
600818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
601818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 *
602818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * DER encoded DigestInfo for SHA256 per RFC 3447:
603818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00
604818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 * 04 20 || H
605818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			 */
606818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hlen += 19;
607818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			os_memcpy(hash,
608818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				  "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
609818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				  "\x03\x04\x02\x01\x05\x00\x04\x20", 19);
610818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
611818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#else /* CONFIG_TLSV12 */
612818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
613818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
614818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			return -1;
615818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TLSV12 */
616818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		} else {
617818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hlen = tls_key_x_server_params_hash(
618818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->rl.tls_version, conn->client_random,
619818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				conn->server_random, server_params,
620818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				pos - server_params, hash);
621818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
622818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
623818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (hlen < 0) {
624818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
625818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
626818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			return -1;
627818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
628818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
629818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash",
630818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			    hash, hlen);
631818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
632818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (conn->test_flags & TLS_BREAK_SRV_KEY_X_HASH) {
633818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params hash");
634818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			hash[hlen - 1] ^= 0x80;
635818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
636818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
637818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
638818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		/*
639818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * RFC 2246, 4.7:
640818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * In digital signing, one-way hash functions are used as input
641818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * for a signing algorithm. A digitally-signed element is
642818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * encoded as an opaque vector <0..2^16-1>, where the length is
643818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * specified by the signing algorithm and key.
644818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 *
645818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * In RSA signing, a 36-byte structure of two hashes (one SHA
646818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * and one MD5) is signed (encrypted with the private key). It
647818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * is encoded with PKCS #1 block type 0 or type 1 as described
648818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 * in [PKCS1].
649818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		 */
650818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		signed_start = pos; /* length to be filled */
651818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		pos += 2;
652818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		clen = end - pos;
653818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (conn->cred == NULL ||
654818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		    crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen,
655818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt						  pos, &clen) < 0) {
656818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)");
657818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
658818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
659818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			return -1;
660818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
661818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		WPA_PUT_BE16(signed_start, clen);
662818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
663818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (conn->test_flags & TLS_BREAK_SRV_KEY_X_SIGNATURE) {
664818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params signature");
665818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			pos[clen - 1] ^= 0x80;
666818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
667818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
668818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
669818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		pos += clen;
670818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	}
671818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
6761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate_request(struct tlsv1_server *conn,
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						u8 **msgpos, u8 *end)
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *rhdr, *hs_start, *hs_length;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!conn->verify_peer) {
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed");
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
705818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send CertificateRequest");
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rhdr = pos;
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_RECORD_HEADER_LEN;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_start = pos;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint24 length (to be filled) */
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hs_length = pos;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - CertificateRequest */
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * enum {
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *   (255)
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * } ClientCertificateType;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * ClientCertificateType certificate_types<1..2^8-1>
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 1;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 1; /* rsa_sign */
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * opaque DistinguishedName<1..2^16-1>
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * DistinguishedName certificate_authorities<3..2^16-1>
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: add support for listing DNs for trusted CAs */
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(pos, 0);
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      rhdr, end - rhdr, hs_start, pos - hs_start,
7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = rhdr + rlen;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*msgpos = pos;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_hello_done(struct tlsv1_server *conn,
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       u8 **msgpos, u8 *end)
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *pos;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
7631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 payload[4];
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
765818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send ServerHelloDone");
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
7701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = payload;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE;
7731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* uint24 length */
7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE24(pos, 0);
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* body - ServerHelloDone (empty) */
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, payload, pos - payload,
7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	tls_verify_hash_add(&conn->verify, payload, pos - payload);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u8 **msgpos, u8 *end)
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
7991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 payload[1];
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
801818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send ChangeCipherSpec");
8021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	payload[0] = TLS_CHANGE_CIPHER_SPEC;
8041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
8061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, payload, sizeof(payload),
8071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "record layer");
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_finished(struct tlsv1_server *conn,
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     u8 **msgpos, u8 *end)
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *pos, *hs_start;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen, hlen;
8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN];
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = *msgpos;
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send Finished");
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Encrypted Handshake Message: Finished */
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
8431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
8441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hlen = SHA256_MAC_LEN;
8451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (conn->verify.sha256_server == NULL ||
8461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    < 0) {
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			conn->verify.sha256_server = NULL;
8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   TLS_ALERT_INTERNAL_ERROR);
8511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return -1;
8521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
8531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		conn->verify.sha256_server = NULL;
8541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	} else {
8551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
8561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = MD5_MAC_LEN;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.md5_server == NULL ||
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.md5_server = NULL;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.md5_server = NULL;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hlen = SHA1_MAC_LEN;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->verify.sha1_server == NULL ||
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       &hlen) < 0) {
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->verify.sha1_server = NULL;
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->verify.sha1_server = NULL;
8781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
8791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12
8811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
8821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (tls_prf(conn->rl.tls_version,
8851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    conn->master_secret, TLS_MASTER_SECRET_LEN,
8861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    "server finished", hash, hlen,
8871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) {
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
8941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			verify_data + 1 + 3, TLS_VERIFY_DATA_LEN);
895818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
896818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	if (conn->test_flags & TLS_BREAK_VERIFY_DATA) {
897818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "TESTING: Break verify_data (server)");
898818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		verify_data[1 + 3 + 1] ^= 0x80;
899818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	}
900818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Handshake */
9031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	pos = hs_start = verify_data;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* HandshakeType msg_type */
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
9061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* uint24 length */
9071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN);
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 3;
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += TLS_VERIFY_DATA_LEN;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
9131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      *msgpos, end - *msgpos, hs_start, pos - hs_start,
9141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      &rlen) < 0) {
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   TLS_ALERT_INTERNAL_ERROR);
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*msgpos += rlen;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *msg, *end, *pos;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t msglen;
931d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	int ocsp_multi = 0;
932d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	char *ocsp_resp = NULL;
933d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	size_t ocsp_resp_len = 0;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
937d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (conn->status_request_multi &&
938d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	    conn->cred->ocsp_stapling_response_multi) {
939d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		ocsp_resp = os_readfile(
940d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			conn->cred->ocsp_stapling_response_multi,
941d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			&ocsp_resp_len);
942d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		ocsp_multi = 1;
943d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	} else if ((conn->status_request || conn->status_request_v2) &&
944d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		   conn->cred->ocsp_stapling_response) {
945d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		ocsp_resp = os_readfile(conn->cred->ocsp_stapling_response,
946d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					&ocsp_resp_len);
947d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
948d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (!ocsp_resp)
949d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		ocsp_resp_len = 0;
950d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
951d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	msglen = 1000 + tls_server_cert_chain_der_len(conn) + ocsp_resp_len;
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(msglen);
954d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (msg == NULL) {
955d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		os_free(ocsp_resp);
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
957d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = msg + msglen;
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_hello(conn, &pos, end) < 0) {
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
964d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		os_free(ocsp_resp);
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conn->use_session_ticket) {
969d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		os_free(ocsp_resp);
970d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Abbreviated handshake using session ticket; RFC 4507 */
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tls_write_server_finished(conn, &pos, end) < 0) {
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(msg);
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*out_len = pos - msg;
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		conn->state = CHANGE_CIPHER_SPEC;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return msg;
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Full handshake */
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_certificate(conn, &pos, end) < 0 ||
987d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	    tls_write_server_certificate_status(conn, &pos, end, ocsp_multi,
988d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt						ocsp_resp, ocsp_resp_len) < 0 ||
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_key_exchange(conn, &pos, end) < 0 ||
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_certificate_request(conn, &pos, end) < 0 ||
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_hello_done(conn, &pos, end) < 0) {
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
993d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		os_free(ocsp_resp);
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
996d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	os_free(ocsp_resp);
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - msg;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = CLIENT_CERTIFICATE;
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn,
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					size_t *out_len)
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *msg, *end, *pos;
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = os_malloc(1000);
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL)
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = msg;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = msg + 1000;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    tls_write_server_finished(conn, &pos, end) < 0) {
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(msg);
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - msg;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Handshake completed successfully");
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	conn->state = ESTABLISHED;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return msg;
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len)
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (conn->state) {
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_HELLO:
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_send_server_hello(conn, out_len);
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case SERVER_CHANGE_CIPHER_SPEC:
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return tls_send_change_cipher_spec(conn, out_len);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (conn->state == ESTABLISHED && conn->use_session_ticket) {
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Abbreviated handshake was already completed. */
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1047818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		tlsv1_server_log(conn, "Unexpected state %d while generating reply",
1048818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				 conn->state);
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     u8 description, size_t *out_len)
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *alert, *pos, *length;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1059818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt	tlsv1_server_log(conn, "Send Alert(%d:%d)", level, description);
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = 0;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	alert = os_malloc(10);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (alert == NULL)
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = alert;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TLSPlaintext */
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ContentType type */
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = TLS_CONTENT_TYPE_ALERT;
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ProtocolVersion version */
10721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
10731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		     TLS_VERSION);
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* uint16 length (to be filled) */
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	length = pos;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 2;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* opaque fragment[TLSPlaintext.length] */
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Alert */
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AlertLevel level */
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = level;
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* AlertDescription description */
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = description;
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(length, pos - length - 2);
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*out_len = pos - alert;
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return alert;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1091