xref: /freebsd/contrib/wpa/src/tls/tlsv1_server.c (revision 7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0)
139beb93cSSam Leffler /*
2f05cddf9SRui Paulo  * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246)
3*4bc52338SCy Schubert  * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/sha1.h"
13e28a4053SRui Paulo #include "crypto/tls.h"
1439beb93cSSam Leffler #include "tlsv1_common.h"
1539beb93cSSam Leffler #include "tlsv1_record.h"
1639beb93cSSam Leffler #include "tlsv1_server.h"
1739beb93cSSam Leffler #include "tlsv1_server_i.h"
1839beb93cSSam Leffler 
1939beb93cSSam Leffler /* TODO:
2039beb93cSSam Leffler  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
2139beb93cSSam Leffler  */
2239beb93cSSam Leffler 
2339beb93cSSam Leffler 
tlsv1_server_log(struct tlsv1_server * conn,const char * fmt,...)245b9c547cSRui Paulo void tlsv1_server_log(struct tlsv1_server *conn, const char *fmt, ...)
255b9c547cSRui Paulo {
265b9c547cSRui Paulo 	va_list ap;
275b9c547cSRui Paulo 	char *buf;
285b9c547cSRui Paulo 	int buflen;
295b9c547cSRui Paulo 
305b9c547cSRui Paulo 	va_start(ap, fmt);
315b9c547cSRui Paulo 	buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
325b9c547cSRui Paulo 	va_end(ap);
335b9c547cSRui Paulo 
345b9c547cSRui Paulo 	buf = os_malloc(buflen);
355b9c547cSRui Paulo 	if (buf == NULL)
365b9c547cSRui Paulo 		return;
375b9c547cSRui Paulo 	va_start(ap, fmt);
385b9c547cSRui Paulo 	vsnprintf(buf, buflen, fmt, ap);
395b9c547cSRui Paulo 	va_end(ap);
405b9c547cSRui Paulo 
415b9c547cSRui Paulo 	wpa_printf(MSG_DEBUG, "TLSv1: %s", buf);
425b9c547cSRui Paulo 	if (conn->log_cb)
435b9c547cSRui Paulo 		conn->log_cb(conn->log_cb_ctx, buf);
445b9c547cSRui Paulo 
455b9c547cSRui Paulo 	os_free(buf);
465b9c547cSRui Paulo }
475b9c547cSRui Paulo 
485b9c547cSRui Paulo 
tlsv1_server_alert(struct tlsv1_server * conn,u8 level,u8 description)4939beb93cSSam Leffler void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description)
5039beb93cSSam Leffler {
5139beb93cSSam Leffler 	conn->alert_level = level;
5239beb93cSSam Leffler 	conn->alert_description = description;
5339beb93cSSam Leffler }
5439beb93cSSam Leffler 
5539beb93cSSam Leffler 
tlsv1_server_derive_keys(struct tlsv1_server * conn,const u8 * pre_master_secret,size_t pre_master_secret_len)5639beb93cSSam Leffler int tlsv1_server_derive_keys(struct tlsv1_server *conn,
5739beb93cSSam Leffler 			     const u8 *pre_master_secret,
5839beb93cSSam Leffler 			     size_t pre_master_secret_len)
5939beb93cSSam Leffler {
6039beb93cSSam Leffler 	u8 seed[2 * TLS_RANDOM_LEN];
6139beb93cSSam Leffler 	u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
6239beb93cSSam Leffler 	u8 *pos;
6339beb93cSSam Leffler 	size_t key_block_len;
6439beb93cSSam Leffler 
6539beb93cSSam Leffler 	if (pre_master_secret) {
6639beb93cSSam Leffler 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
6739beb93cSSam Leffler 				pre_master_secret, pre_master_secret_len);
6839beb93cSSam Leffler 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
6939beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
7039beb93cSSam Leffler 			  TLS_RANDOM_LEN);
71f05cddf9SRui Paulo 		if (tls_prf(conn->rl.tls_version,
72f05cddf9SRui Paulo 			    pre_master_secret, pre_master_secret_len,
7339beb93cSSam Leffler 			    "master secret", seed, 2 * TLS_RANDOM_LEN,
7439beb93cSSam Leffler 			    conn->master_secret, TLS_MASTER_SECRET_LEN)) {
7539beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
7639beb93cSSam Leffler 				   "master_secret");
7739beb93cSSam Leffler 			return -1;
7839beb93cSSam Leffler 		}
7939beb93cSSam Leffler 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
8039beb93cSSam Leffler 				conn->master_secret, TLS_MASTER_SECRET_LEN);
8139beb93cSSam Leffler 	}
8239beb93cSSam Leffler 
8339beb93cSSam Leffler 	os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
8439beb93cSSam Leffler 	os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
8539beb93cSSam Leffler 	key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len +
8639beb93cSSam Leffler 			     conn->rl.iv_size);
87f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
88f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
8939beb93cSSam Leffler 		    "key expansion", seed, 2 * TLS_RANDOM_LEN,
9039beb93cSSam Leffler 		    key_block, key_block_len)) {
9139beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
9239beb93cSSam Leffler 		return -1;
9339beb93cSSam Leffler 	}
9439beb93cSSam Leffler 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
9539beb93cSSam Leffler 			key_block, key_block_len);
9639beb93cSSam Leffler 
9739beb93cSSam Leffler 	pos = key_block;
9839beb93cSSam Leffler 
9939beb93cSSam Leffler 	/* client_write_MAC_secret */
10039beb93cSSam Leffler 	os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
10139beb93cSSam Leffler 	pos += conn->rl.hash_size;
10239beb93cSSam Leffler 	/* server_write_MAC_secret */
10339beb93cSSam Leffler 	os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
10439beb93cSSam Leffler 	pos += conn->rl.hash_size;
10539beb93cSSam Leffler 
10639beb93cSSam Leffler 	/* client_write_key */
10739beb93cSSam Leffler 	os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
10839beb93cSSam Leffler 	pos += conn->rl.key_material_len;
10939beb93cSSam Leffler 	/* server_write_key */
11039beb93cSSam Leffler 	os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
11139beb93cSSam Leffler 	pos += conn->rl.key_material_len;
11239beb93cSSam Leffler 
11339beb93cSSam Leffler 	/* client_write_IV */
11439beb93cSSam Leffler 	os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
11539beb93cSSam Leffler 	pos += conn->rl.iv_size;
11639beb93cSSam Leffler 	/* server_write_IV */
11739beb93cSSam Leffler 	os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
11839beb93cSSam Leffler 	pos += conn->rl.iv_size;
11939beb93cSSam Leffler 
12039beb93cSSam Leffler 	return 0;
12139beb93cSSam Leffler }
12239beb93cSSam Leffler 
12339beb93cSSam Leffler 
12439beb93cSSam Leffler /**
12539beb93cSSam Leffler  * tlsv1_server_handshake - Process TLS handshake
12639beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
12739beb93cSSam Leffler  * @in_data: Input data from TLS peer
12839beb93cSSam Leffler  * @in_len: Input data length
12939beb93cSSam Leffler  * @out_len: Length of the output buffer.
13039beb93cSSam Leffler  * Returns: Pointer to output data, %NULL on failure
13139beb93cSSam Leffler  */
tlsv1_server_handshake(struct tlsv1_server * conn,const u8 * in_data,size_t in_len,size_t * out_len)13239beb93cSSam Leffler u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
13339beb93cSSam Leffler 			    const u8 *in_data, size_t in_len,
13439beb93cSSam Leffler 			    size_t *out_len)
13539beb93cSSam Leffler {
13639beb93cSSam Leffler 	const u8 *pos, *end;
13739beb93cSSam Leffler 	u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;
13839beb93cSSam Leffler 	size_t in_msg_len;
139f05cddf9SRui Paulo 	int used;
14039beb93cSSam Leffler 
14139beb93cSSam Leffler 	if (in_data == NULL || in_len == 0) {
14239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: No input data to server");
14339beb93cSSam Leffler 		return NULL;
14439beb93cSSam Leffler 	}
14539beb93cSSam Leffler 
14639beb93cSSam Leffler 	pos = in_data;
14739beb93cSSam Leffler 	end = in_data + in_len;
14839beb93cSSam Leffler 	in_msg = os_malloc(in_len);
14939beb93cSSam Leffler 	if (in_msg == NULL)
15039beb93cSSam Leffler 		return NULL;
15139beb93cSSam Leffler 
15239beb93cSSam Leffler 	/* Each received packet may include multiple records */
15339beb93cSSam Leffler 	while (pos < end) {
15439beb93cSSam Leffler 		in_msg_len = in_len;
155f05cddf9SRui Paulo 		used = tlsv1_record_receive(&conn->rl, pos, end - pos,
156f05cddf9SRui Paulo 					    in_msg, &in_msg_len, &alert);
157f05cddf9SRui Paulo 		if (used < 0) {
15839beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
15939beb93cSSam Leffler 				   "record failed");
16039beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
16139beb93cSSam Leffler 			goto failed;
16239beb93cSSam Leffler 		}
163f05cddf9SRui Paulo 		if (used == 0) {
164f05cddf9SRui Paulo 			/* need more data */
165f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not "
166f05cddf9SRui Paulo 				   "yet supported");
167*4bc52338SCy Schubert 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
168*4bc52338SCy Schubert 					   TLS_ALERT_INTERNAL_ERROR);
169f05cddf9SRui Paulo 			goto failed;
170f05cddf9SRui Paulo 		}
17139beb93cSSam Leffler 		ct = pos[0];
17239beb93cSSam Leffler 
17339beb93cSSam Leffler 		in_pos = in_msg;
17439beb93cSSam Leffler 		in_end = in_msg + in_msg_len;
17539beb93cSSam Leffler 
17639beb93cSSam Leffler 		/* Each received record may include multiple messages of the
17739beb93cSSam Leffler 		 * same ContentType. */
17839beb93cSSam Leffler 		while (in_pos < in_end) {
17939beb93cSSam Leffler 			in_msg_len = in_end - in_pos;
18039beb93cSSam Leffler 			if (tlsv1_server_process_handshake(conn, ct, in_pos,
18139beb93cSSam Leffler 							   &in_msg_len) < 0)
18239beb93cSSam Leffler 				goto failed;
18339beb93cSSam Leffler 			in_pos += in_msg_len;
18439beb93cSSam Leffler 		}
18539beb93cSSam Leffler 
186f05cddf9SRui Paulo 		pos += used;
18739beb93cSSam Leffler 	}
18839beb93cSSam Leffler 
18939beb93cSSam Leffler 	os_free(in_msg);
19039beb93cSSam Leffler 	in_msg = NULL;
19139beb93cSSam Leffler 
19239beb93cSSam Leffler 	msg = tlsv1_server_handshake_write(conn, out_len);
19339beb93cSSam Leffler 
19439beb93cSSam Leffler failed:
19539beb93cSSam Leffler 	os_free(in_msg);
19639beb93cSSam Leffler 	if (conn->alert_level) {
19739beb93cSSam Leffler 		if (conn->state == FAILED) {
19839beb93cSSam Leffler 			/* Avoid alert loops */
19939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop");
20039beb93cSSam Leffler 			os_free(msg);
20139beb93cSSam Leffler 			return NULL;
20239beb93cSSam Leffler 		}
20339beb93cSSam Leffler 		conn->state = FAILED;
20439beb93cSSam Leffler 		os_free(msg);
20539beb93cSSam Leffler 		msg = tlsv1_server_send_alert(conn, conn->alert_level,
20639beb93cSSam Leffler 					      conn->alert_description,
20739beb93cSSam Leffler 					      out_len);
208*4bc52338SCy Schubert 		conn->write_alerts++;
20939beb93cSSam Leffler 	}
21039beb93cSSam Leffler 
21139beb93cSSam Leffler 	return msg;
21239beb93cSSam Leffler }
21339beb93cSSam Leffler 
21439beb93cSSam Leffler 
21539beb93cSSam Leffler /**
21639beb93cSSam Leffler  * tlsv1_server_encrypt - Encrypt data into TLS tunnel
21739beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
21839beb93cSSam Leffler  * @in_data: Pointer to plaintext data to be encrypted
21939beb93cSSam Leffler  * @in_len: Input buffer length
22039beb93cSSam Leffler  * @out_data: Pointer to output buffer (encrypted TLS data)
22139beb93cSSam Leffler  * @out_len: Maximum out_data length
22239beb93cSSam Leffler  * Returns: Number of bytes written to out_data, -1 on failure
22339beb93cSSam Leffler  *
22439beb93cSSam Leffler  * This function is used after TLS handshake has been completed successfully to
22539beb93cSSam Leffler  * send data in the encrypted tunnel.
22639beb93cSSam Leffler  */
tlsv1_server_encrypt(struct tlsv1_server * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)22739beb93cSSam Leffler int tlsv1_server_encrypt(struct tlsv1_server *conn,
22839beb93cSSam Leffler 			 const u8 *in_data, size_t in_len,
22939beb93cSSam Leffler 			 u8 *out_data, size_t out_len)
23039beb93cSSam Leffler {
23139beb93cSSam Leffler 	size_t rlen;
23239beb93cSSam Leffler 
23339beb93cSSam Leffler 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
23439beb93cSSam Leffler 			in_data, in_len);
23539beb93cSSam Leffler 
23639beb93cSSam Leffler 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
237f05cddf9SRui Paulo 			      out_data, out_len, in_data, in_len, &rlen) < 0) {
23839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
23939beb93cSSam Leffler 		tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
24039beb93cSSam Leffler 				   TLS_ALERT_INTERNAL_ERROR);
24139beb93cSSam Leffler 		return -1;
24239beb93cSSam Leffler 	}
24339beb93cSSam Leffler 
24439beb93cSSam Leffler 	return rlen;
24539beb93cSSam Leffler }
24639beb93cSSam Leffler 
24739beb93cSSam Leffler 
24839beb93cSSam Leffler /**
24939beb93cSSam Leffler  * tlsv1_server_decrypt - Decrypt data from TLS tunnel
25039beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
25139beb93cSSam Leffler  * @in_data: Pointer to input buffer (encrypted TLS data)
25239beb93cSSam Leffler  * @in_len: Input buffer length
25339beb93cSSam Leffler  * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
25439beb93cSSam Leffler  * @out_len: Maximum out_data length
25539beb93cSSam Leffler  * Returns: Number of bytes written to out_data, -1 on failure
25639beb93cSSam Leffler  *
25739beb93cSSam Leffler  * This function is used after TLS handshake has been completed successfully to
25839beb93cSSam Leffler  * receive data from the encrypted tunnel.
25939beb93cSSam Leffler  */
tlsv1_server_decrypt(struct tlsv1_server * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)26039beb93cSSam Leffler int tlsv1_server_decrypt(struct tlsv1_server *conn,
26139beb93cSSam Leffler 			 const u8 *in_data, size_t in_len,
26239beb93cSSam Leffler 			 u8 *out_data, size_t out_len)
26339beb93cSSam Leffler {
26439beb93cSSam Leffler 	const u8 *in_end, *pos;
265f05cddf9SRui Paulo 	int used;
266f05cddf9SRui Paulo 	u8 alert, *out_end, *out_pos, ct;
26739beb93cSSam Leffler 	size_t olen;
26839beb93cSSam Leffler 
26939beb93cSSam Leffler 	pos = in_data;
27039beb93cSSam Leffler 	in_end = in_data + in_len;
27139beb93cSSam Leffler 	out_pos = out_data;
27239beb93cSSam Leffler 	out_end = out_data + out_len;
27339beb93cSSam Leffler 
27439beb93cSSam Leffler 	while (pos < in_end) {
275f05cddf9SRui Paulo 		ct = pos[0];
276f05cddf9SRui Paulo 		olen = out_end - out_pos;
277f05cddf9SRui Paulo 		used = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
278f05cddf9SRui Paulo 					    out_pos, &olen, &alert);
279f05cddf9SRui Paulo 		if (used < 0) {
2805b9c547cSRui Paulo 			tlsv1_server_log(conn, "Record layer processing failed");
281f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
282f05cddf9SRui Paulo 			return -1;
283f05cddf9SRui Paulo 		}
284f05cddf9SRui Paulo 		if (used == 0) {
285f05cddf9SRui Paulo 			/* need more data */
286f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not "
287f05cddf9SRui Paulo 				   "yet supported");
288f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
289f05cddf9SRui Paulo 			return -1;
290f05cddf9SRui Paulo 		}
291f05cddf9SRui Paulo 
292f05cddf9SRui Paulo 		if (ct == TLS_CONTENT_TYPE_ALERT) {
293f05cddf9SRui Paulo 			if (olen < 2) {
2945b9c547cSRui Paulo 				tlsv1_server_log(conn, "Alert underflow");
295f05cddf9SRui Paulo 				tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
296f05cddf9SRui Paulo 						   TLS_ALERT_DECODE_ERROR);
297f05cddf9SRui Paulo 				return -1;
298f05cddf9SRui Paulo 			}
2995b9c547cSRui Paulo 			tlsv1_server_log(conn, "Received alert %d:%d",
300f05cddf9SRui Paulo 					 out_pos[0], out_pos[1]);
301*4bc52338SCy Schubert 			conn->read_alerts++;
302f05cddf9SRui Paulo 			if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) {
303f05cddf9SRui Paulo 				/* Continue processing */
304f05cddf9SRui Paulo 				pos += used;
305f05cddf9SRui Paulo 				continue;
306f05cddf9SRui Paulo 			}
307f05cddf9SRui Paulo 
308f05cddf9SRui Paulo 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
309f05cddf9SRui Paulo 					   out_pos[1]);
310f05cddf9SRui Paulo 			return -1;
311f05cddf9SRui Paulo 		}
312f05cddf9SRui Paulo 
313f05cddf9SRui Paulo 		if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
3145b9c547cSRui Paulo 			tlsv1_server_log(conn, "Unexpected content type 0x%x",
3155b9c547cSRui Paulo 					 pos[0]);
31639beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
31739beb93cSSam Leffler 					   TLS_ALERT_UNEXPECTED_MESSAGE);
31839beb93cSSam Leffler 			return -1;
31939beb93cSSam Leffler 		}
32039beb93cSSam Leffler 
3215b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
3225b9c547cSRui Paulo 		if ((conn->test_flags &
3235b9c547cSRui Paulo 		     (TLS_BREAK_VERIFY_DATA | TLS_BREAK_SRV_KEY_X_HASH |
3245b9c547cSRui Paulo 		      TLS_BREAK_SRV_KEY_X_SIGNATURE)) &&
3255b9c547cSRui Paulo 		    !conn->test_failure_reported) {
3265b9c547cSRui Paulo 			tlsv1_server_log(conn, "TEST-FAILURE: Client ApplData received after invalid handshake");
3275b9c547cSRui Paulo 			conn->test_failure_reported = 1;
3285b9c547cSRui Paulo 		}
3295b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
3305b9c547cSRui Paulo 
33139beb93cSSam Leffler 		out_pos += olen;
33239beb93cSSam Leffler 		if (out_pos > out_end) {
33339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough "
33439beb93cSSam Leffler 				   "for processing the received record");
33539beb93cSSam Leffler 			tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
33639beb93cSSam Leffler 					   TLS_ALERT_INTERNAL_ERROR);
33739beb93cSSam Leffler 			return -1;
33839beb93cSSam Leffler 		}
33939beb93cSSam Leffler 
340f05cddf9SRui Paulo 		pos += used;
34139beb93cSSam Leffler 	}
34239beb93cSSam Leffler 
34339beb93cSSam Leffler 	return out_pos - out_data;
34439beb93cSSam Leffler }
34539beb93cSSam Leffler 
34639beb93cSSam Leffler 
34739beb93cSSam Leffler /**
34839beb93cSSam Leffler  * tlsv1_server_global_init - Initialize TLSv1 server
34939beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
35039beb93cSSam Leffler  *
35139beb93cSSam Leffler  * This function must be called before using any other TLSv1 server functions.
35239beb93cSSam Leffler  */
tlsv1_server_global_init(void)35339beb93cSSam Leffler int tlsv1_server_global_init(void)
35439beb93cSSam Leffler {
35539beb93cSSam Leffler 	return crypto_global_init();
35639beb93cSSam Leffler }
35739beb93cSSam Leffler 
35839beb93cSSam Leffler 
35939beb93cSSam Leffler /**
36039beb93cSSam Leffler  * tlsv1_server_global_deinit - Deinitialize TLSv1 server
36139beb93cSSam Leffler  *
36239beb93cSSam Leffler  * This function can be used to deinitialize the TLSv1 server that was
36339beb93cSSam Leffler  * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions
36439beb93cSSam Leffler  * can be called after this before calling tlsv1_server_global_init() again.
36539beb93cSSam Leffler  */
tlsv1_server_global_deinit(void)36639beb93cSSam Leffler void tlsv1_server_global_deinit(void)
36739beb93cSSam Leffler {
36839beb93cSSam Leffler 	crypto_global_deinit();
36939beb93cSSam Leffler }
37039beb93cSSam Leffler 
37139beb93cSSam Leffler 
37239beb93cSSam Leffler /**
37339beb93cSSam Leffler  * tlsv1_server_init - Initialize TLSv1 server connection
37439beb93cSSam Leffler  * @cred: Pointer to server credentials from tlsv1_server_cred_alloc()
37539beb93cSSam Leffler  * Returns: Pointer to TLSv1 server connection data or %NULL on failure
37639beb93cSSam Leffler  */
tlsv1_server_init(struct tlsv1_credentials * cred)37739beb93cSSam Leffler struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred)
37839beb93cSSam Leffler {
37939beb93cSSam Leffler 	struct tlsv1_server *conn;
38039beb93cSSam Leffler 	size_t count;
38139beb93cSSam Leffler 	u16 *suites;
38239beb93cSSam Leffler 
38339beb93cSSam Leffler 	conn = os_zalloc(sizeof(*conn));
38439beb93cSSam Leffler 	if (conn == NULL)
38539beb93cSSam Leffler 		return NULL;
38639beb93cSSam Leffler 
38739beb93cSSam Leffler 	conn->cred = cred;
38839beb93cSSam Leffler 
38939beb93cSSam Leffler 	conn->state = CLIENT_HELLO;
39039beb93cSSam Leffler 
39139beb93cSSam Leffler 	if (tls_verify_hash_init(&conn->verify) < 0) {
39239beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
39339beb93cSSam Leffler 			   "hash");
39439beb93cSSam Leffler 		os_free(conn);
39539beb93cSSam Leffler 		return NULL;
39639beb93cSSam Leffler 	}
39739beb93cSSam Leffler 
39839beb93cSSam Leffler 	count = 0;
39939beb93cSSam Leffler 	suites = conn->cipher_suites;
4005b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
4015b9c547cSRui Paulo 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
4025b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
40339beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
4045b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
4055b9c547cSRui Paulo 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
4065b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
40739beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
4085b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
40939beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
41039beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
41139beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
41239beb93cSSam Leffler 	conn->num_cipher_suites = count;
41339beb93cSSam Leffler 
41439beb93cSSam Leffler 	return conn;
41539beb93cSSam Leffler }
41639beb93cSSam Leffler 
41739beb93cSSam Leffler 
tlsv1_server_clear_data(struct tlsv1_server * conn)41839beb93cSSam Leffler static void tlsv1_server_clear_data(struct tlsv1_server *conn)
41939beb93cSSam Leffler {
42039beb93cSSam Leffler 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
42139beb93cSSam Leffler 	tlsv1_record_change_write_cipher(&conn->rl);
42239beb93cSSam Leffler 	tlsv1_record_change_read_cipher(&conn->rl);
42339beb93cSSam Leffler 	tls_verify_hash_free(&conn->verify);
42439beb93cSSam Leffler 
42539beb93cSSam Leffler 	crypto_public_key_free(conn->client_rsa_key);
42639beb93cSSam Leffler 	conn->client_rsa_key = NULL;
42739beb93cSSam Leffler 
42839beb93cSSam Leffler 	os_free(conn->session_ticket);
42939beb93cSSam Leffler 	conn->session_ticket = NULL;
43039beb93cSSam Leffler 	conn->session_ticket_len = 0;
43139beb93cSSam Leffler 	conn->use_session_ticket = 0;
43239beb93cSSam Leffler 
43339beb93cSSam Leffler 	os_free(conn->dh_secret);
43439beb93cSSam Leffler 	conn->dh_secret = NULL;
43539beb93cSSam Leffler 	conn->dh_secret_len = 0;
43639beb93cSSam Leffler }
43739beb93cSSam Leffler 
43839beb93cSSam Leffler 
43939beb93cSSam Leffler /**
44039beb93cSSam Leffler  * tlsv1_server_deinit - Deinitialize TLSv1 server connection
44139beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
44239beb93cSSam Leffler  */
tlsv1_server_deinit(struct tlsv1_server * conn)44339beb93cSSam Leffler void tlsv1_server_deinit(struct tlsv1_server *conn)
44439beb93cSSam Leffler {
44539beb93cSSam Leffler 	tlsv1_server_clear_data(conn);
44639beb93cSSam Leffler 	os_free(conn);
44739beb93cSSam Leffler }
44839beb93cSSam Leffler 
44939beb93cSSam Leffler 
45039beb93cSSam Leffler /**
45139beb93cSSam Leffler  * tlsv1_server_established - Check whether connection has been established
45239beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
45339beb93cSSam Leffler  * Returns: 1 if connection is established, 0 if not
45439beb93cSSam Leffler  */
tlsv1_server_established(struct tlsv1_server * conn)45539beb93cSSam Leffler int tlsv1_server_established(struct tlsv1_server *conn)
45639beb93cSSam Leffler {
45739beb93cSSam Leffler 	return conn->state == ESTABLISHED;
45839beb93cSSam Leffler }
45939beb93cSSam Leffler 
46039beb93cSSam Leffler 
46139beb93cSSam Leffler /**
46239beb93cSSam Leffler  * tlsv1_server_prf - Use TLS-PRF to derive keying material
46339beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
46439beb93cSSam Leffler  * @label: Label (e.g., description of the key) for PRF
465*4bc52338SCy Schubert  * @context: Optional extra upper-layer context (max len 2^16)
466*4bc52338SCy Schubert  * @context_len: The length of the context value
46739beb93cSSam Leffler  * @server_random_first: seed is 0 = client_random|server_random,
46839beb93cSSam Leffler  * 1 = server_random|client_random
46939beb93cSSam Leffler  * @out: Buffer for output data from TLS-PRF
47039beb93cSSam Leffler  * @out_len: Length of the output buffer
47139beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
47239beb93cSSam Leffler  */
tlsv1_server_prf(struct tlsv1_server * conn,const char * label,const u8 * context,size_t context_len,int server_random_first,u8 * out,size_t out_len)47339beb93cSSam Leffler int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
474*4bc52338SCy Schubert 		     const u8 *context, size_t context_len,
47539beb93cSSam Leffler 		     int server_random_first, u8 *out, size_t out_len)
47639beb93cSSam Leffler {
477*4bc52338SCy Schubert 	u8 *seed, *pos;
478*4bc52338SCy Schubert 	size_t seed_len = 2 * TLS_RANDOM_LEN;
479*4bc52338SCy Schubert 	int res;
48039beb93cSSam Leffler 
48139beb93cSSam Leffler 	if (conn->state != ESTABLISHED)
48239beb93cSSam Leffler 		return -1;
48339beb93cSSam Leffler 
484*4bc52338SCy Schubert 	if (context_len > 65535)
485*4bc52338SCy Schubert 		return -1;
486*4bc52338SCy Schubert 
487*4bc52338SCy Schubert 	if (context)
488*4bc52338SCy Schubert 		seed_len += 2 + context_len;
489*4bc52338SCy Schubert 
490*4bc52338SCy Schubert 	seed = os_malloc(seed_len);
491*4bc52338SCy Schubert 	if (!seed)
492*4bc52338SCy Schubert 		return -1;
493*4bc52338SCy Schubert 
49439beb93cSSam Leffler 	if (server_random_first) {
49539beb93cSSam Leffler 		os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
49639beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
49739beb93cSSam Leffler 			  TLS_RANDOM_LEN);
49839beb93cSSam Leffler 	} else {
49939beb93cSSam Leffler 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
50039beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
50139beb93cSSam Leffler 			  TLS_RANDOM_LEN);
50239beb93cSSam Leffler 	}
50339beb93cSSam Leffler 
504*4bc52338SCy Schubert 	if (context) {
505*4bc52338SCy Schubert 		pos = seed + 2 * TLS_RANDOM_LEN;
506*4bc52338SCy Schubert 		WPA_PUT_BE16(pos, context_len);
507*4bc52338SCy Schubert 		pos += 2;
508*4bc52338SCy Schubert 		os_memcpy(pos, context, context_len);
509*4bc52338SCy Schubert 	}
510*4bc52338SCy Schubert 
511*4bc52338SCy Schubert 	res = tls_prf(conn->rl.tls_version,
512f05cddf9SRui Paulo 		      conn->master_secret, TLS_MASTER_SECRET_LEN,
513*4bc52338SCy Schubert 		      label, seed, seed_len, out, out_len);
514*4bc52338SCy Schubert 	os_free(seed);
515*4bc52338SCy Schubert 	return res;
51639beb93cSSam Leffler }
51739beb93cSSam Leffler 
51839beb93cSSam Leffler 
51939beb93cSSam Leffler /**
52039beb93cSSam Leffler  * tlsv1_server_get_cipher - Get current cipher name
52139beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
52239beb93cSSam Leffler  * @buf: Buffer for the cipher name
52339beb93cSSam Leffler  * @buflen: buf size
52439beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
52539beb93cSSam Leffler  *
52639beb93cSSam Leffler  * Get the name of the currently used cipher.
52739beb93cSSam Leffler  */
tlsv1_server_get_cipher(struct tlsv1_server * conn,char * buf,size_t buflen)52839beb93cSSam Leffler int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf,
52939beb93cSSam Leffler 			    size_t buflen)
53039beb93cSSam Leffler {
53139beb93cSSam Leffler 	char *cipher;
53239beb93cSSam Leffler 
53339beb93cSSam Leffler 	switch (conn->rl.cipher_suite) {
53439beb93cSSam Leffler 	case TLS_RSA_WITH_RC4_128_MD5:
53539beb93cSSam Leffler 		cipher = "RC4-MD5";
53639beb93cSSam Leffler 		break;
53739beb93cSSam Leffler 	case TLS_RSA_WITH_RC4_128_SHA:
53839beb93cSSam Leffler 		cipher = "RC4-SHA";
53939beb93cSSam Leffler 		break;
54039beb93cSSam Leffler 	case TLS_RSA_WITH_DES_CBC_SHA:
54139beb93cSSam Leffler 		cipher = "DES-CBC-SHA";
54239beb93cSSam Leffler 		break;
54339beb93cSSam Leffler 	case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
54439beb93cSSam Leffler 		cipher = "DES-CBC3-SHA";
54539beb93cSSam Leffler 		break;
5465b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_DES_CBC_SHA:
5475b9c547cSRui Paulo 		cipher = "DHE-RSA-DES-CBC-SHA";
5485b9c547cSRui Paulo 		break;
5495b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
5505b9c547cSRui Paulo 		cipher = "DHE-RSA-DES-CBC3-SHA";
5515b9c547cSRui Paulo 		break;
5525b9c547cSRui Paulo 	case TLS_DH_anon_WITH_RC4_128_MD5:
5535b9c547cSRui Paulo 		cipher = "ADH-RC4-MD5";
5545b9c547cSRui Paulo 		break;
5555b9c547cSRui Paulo 	case TLS_DH_anon_WITH_DES_CBC_SHA:
5565b9c547cSRui Paulo 		cipher = "ADH-DES-SHA";
5575b9c547cSRui Paulo 		break;
5585b9c547cSRui Paulo 	case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
5595b9c547cSRui Paulo 		cipher = "ADH-DES-CBC3-SHA";
5605b9c547cSRui Paulo 		break;
5615b9c547cSRui Paulo 	case TLS_RSA_WITH_AES_128_CBC_SHA:
5625b9c547cSRui Paulo 		cipher = "AES-128-SHA";
5635b9c547cSRui Paulo 		break;
5645b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
5655b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-128-SHA";
5665b9c547cSRui Paulo 		break;
56739beb93cSSam Leffler 	case TLS_DH_anon_WITH_AES_128_CBC_SHA:
56839beb93cSSam Leffler 		cipher = "ADH-AES-128-SHA";
56939beb93cSSam Leffler 		break;
57039beb93cSSam Leffler 	case TLS_RSA_WITH_AES_256_CBC_SHA:
57139beb93cSSam Leffler 		cipher = "AES-256-SHA";
57239beb93cSSam Leffler 		break;
5735b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
5745b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-256-SHA";
5755b9c547cSRui Paulo 		break;
5765b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_256_CBC_SHA:
5775b9c547cSRui Paulo 		cipher = "ADH-AES-256-SHA";
5785b9c547cSRui Paulo 		break;
5795b9c547cSRui Paulo 	case TLS_RSA_WITH_AES_128_CBC_SHA256:
5805b9c547cSRui Paulo 		cipher = "AES-128-SHA256";
5815b9c547cSRui Paulo 		break;
5825b9c547cSRui Paulo 	case TLS_RSA_WITH_AES_256_CBC_SHA256:
5835b9c547cSRui Paulo 		cipher = "AES-256-SHA256";
5845b9c547cSRui Paulo 		break;
5855b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
5865b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-128-SHA256";
5875b9c547cSRui Paulo 		break;
5885b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
5895b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-256-SHA256";
5905b9c547cSRui Paulo 		break;
5915b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
5925b9c547cSRui Paulo 		cipher = "ADH-AES-128-SHA256";
5935b9c547cSRui Paulo 		break;
5945b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
5955b9c547cSRui Paulo 		cipher = "ADH-AES-256-SHA256";
59639beb93cSSam Leffler 		break;
59739beb93cSSam Leffler 	default:
59839beb93cSSam Leffler 		return -1;
59939beb93cSSam Leffler 	}
60039beb93cSSam Leffler 
60139beb93cSSam Leffler 	if (os_strlcpy(buf, cipher, buflen) >= buflen)
60239beb93cSSam Leffler 		return -1;
60339beb93cSSam Leffler 	return 0;
60439beb93cSSam Leffler }
60539beb93cSSam Leffler 
60639beb93cSSam Leffler 
60739beb93cSSam Leffler /**
60839beb93cSSam Leffler  * tlsv1_server_shutdown - Shutdown TLS connection
60939beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
61039beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
61139beb93cSSam Leffler  */
tlsv1_server_shutdown(struct tlsv1_server * conn)61239beb93cSSam Leffler int tlsv1_server_shutdown(struct tlsv1_server *conn)
61339beb93cSSam Leffler {
61439beb93cSSam Leffler 	conn->state = CLIENT_HELLO;
61539beb93cSSam Leffler 
61639beb93cSSam Leffler 	if (tls_verify_hash_init(&conn->verify) < 0) {
61739beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
61839beb93cSSam Leffler 			   "hash");
61939beb93cSSam Leffler 		return -1;
62039beb93cSSam Leffler 	}
62139beb93cSSam Leffler 
62239beb93cSSam Leffler 	tlsv1_server_clear_data(conn);
62339beb93cSSam Leffler 
62439beb93cSSam Leffler 	return 0;
62539beb93cSSam Leffler }
62639beb93cSSam Leffler 
62739beb93cSSam Leffler 
62839beb93cSSam Leffler /**
62939beb93cSSam Leffler  * tlsv1_server_resumed - Was session resumption used
63039beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
63139beb93cSSam Leffler  * Returns: 1 if current session used session resumption, 0 if not
63239beb93cSSam Leffler  */
tlsv1_server_resumed(struct tlsv1_server * conn)63339beb93cSSam Leffler int tlsv1_server_resumed(struct tlsv1_server *conn)
63439beb93cSSam Leffler {
63539beb93cSSam Leffler 	return 0;
63639beb93cSSam Leffler }
63739beb93cSSam Leffler 
63839beb93cSSam Leffler 
63939beb93cSSam Leffler /**
640325151a3SRui Paulo  * tlsv1_server_get_random - Get random data from TLS connection
64139beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
642325151a3SRui Paulo  * @keys: Structure of random data (filled on success)
64339beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
64439beb93cSSam Leffler  */
tlsv1_server_get_random(struct tlsv1_server * conn,struct tls_random * keys)645325151a3SRui Paulo int tlsv1_server_get_random(struct tlsv1_server *conn, struct tls_random *keys)
64639beb93cSSam Leffler {
64739beb93cSSam Leffler 	os_memset(keys, 0, sizeof(*keys));
64839beb93cSSam Leffler 	if (conn->state == CLIENT_HELLO)
64939beb93cSSam Leffler 		return -1;
65039beb93cSSam Leffler 
65139beb93cSSam Leffler 	keys->client_random = conn->client_random;
65239beb93cSSam Leffler 	keys->client_random_len = TLS_RANDOM_LEN;
65339beb93cSSam Leffler 
65439beb93cSSam Leffler 	if (conn->state != SERVER_HELLO) {
65539beb93cSSam Leffler 		keys->server_random = conn->server_random;
65639beb93cSSam Leffler 		keys->server_random_len = TLS_RANDOM_LEN;
65739beb93cSSam Leffler 	}
65839beb93cSSam Leffler 
65939beb93cSSam Leffler 	return 0;
66039beb93cSSam Leffler }
66139beb93cSSam Leffler 
66239beb93cSSam Leffler 
66339beb93cSSam Leffler /**
66439beb93cSSam Leffler  * tlsv1_server_get_keyblock_size - Get TLS key_block size
66539beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
66639beb93cSSam Leffler  * Returns: Size of the key_block for the negotiated cipher suite or -1 on
66739beb93cSSam Leffler  * failure
66839beb93cSSam Leffler  */
tlsv1_server_get_keyblock_size(struct tlsv1_server * conn)66939beb93cSSam Leffler int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn)
67039beb93cSSam Leffler {
67139beb93cSSam Leffler 	if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
67239beb93cSSam Leffler 		return -1;
67339beb93cSSam Leffler 
67439beb93cSSam Leffler 	return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
67539beb93cSSam Leffler 		    conn->rl.iv_size);
67639beb93cSSam Leffler }
67739beb93cSSam Leffler 
67839beb93cSSam Leffler 
67939beb93cSSam Leffler /**
68039beb93cSSam Leffler  * tlsv1_server_set_cipher_list - Configure acceptable cipher suites
68139beb93cSSam Leffler  * @conn: TLSv1 server connection data from tlsv1_server_init()
68239beb93cSSam Leffler  * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
68339beb93cSSam Leffler  * (TLS_CIPHER_*).
68439beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
68539beb93cSSam Leffler  */
tlsv1_server_set_cipher_list(struct tlsv1_server * conn,u8 * ciphers)68639beb93cSSam Leffler int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers)
68739beb93cSSam Leffler {
68839beb93cSSam Leffler 	size_t count;
68939beb93cSSam Leffler 	u16 *suites;
69039beb93cSSam Leffler 
69139beb93cSSam Leffler 	/* TODO: implement proper configuration of cipher suites */
69239beb93cSSam Leffler 	if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
69339beb93cSSam Leffler 		count = 0;
69439beb93cSSam Leffler 		suites = conn->cipher_suites;
69539beb93cSSam Leffler 		suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
69639beb93cSSam Leffler 		suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
69739beb93cSSam Leffler 		suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
69839beb93cSSam Leffler 		suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
69939beb93cSSam Leffler 		suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
70039beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
70139beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
70239beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
70339beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
70439beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
70539beb93cSSam Leffler 		conn->num_cipher_suites = count;
70639beb93cSSam Leffler 	}
70739beb93cSSam Leffler 
70839beb93cSSam Leffler 	return 0;
70939beb93cSSam Leffler }
71039beb93cSSam Leffler 
71139beb93cSSam Leffler 
tlsv1_server_set_verify(struct tlsv1_server * conn,int verify_peer)71239beb93cSSam Leffler int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer)
71339beb93cSSam Leffler {
71439beb93cSSam Leffler 	conn->verify_peer = verify_peer;
71539beb93cSSam Leffler 	return 0;
71639beb93cSSam Leffler }
71739beb93cSSam Leffler 
71839beb93cSSam Leffler 
tlsv1_server_set_session_ticket_cb(struct tlsv1_server * conn,tlsv1_server_session_ticket_cb cb,void * ctx)71939beb93cSSam Leffler void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn,
72039beb93cSSam Leffler 					tlsv1_server_session_ticket_cb cb,
72139beb93cSSam Leffler 					void *ctx)
72239beb93cSSam Leffler {
72339beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
72439beb93cSSam Leffler 		   cb, ctx);
72539beb93cSSam Leffler 	conn->session_ticket_cb = cb;
72639beb93cSSam Leffler 	conn->session_ticket_cb_ctx = ctx;
72739beb93cSSam Leffler }
7285b9c547cSRui Paulo 
7295b9c547cSRui Paulo 
tlsv1_server_set_log_cb(struct tlsv1_server * conn,void (* cb)(void * ctx,const char * msg),void * ctx)7305b9c547cSRui Paulo void tlsv1_server_set_log_cb(struct tlsv1_server *conn,
7315b9c547cSRui Paulo 			     void (*cb)(void *ctx, const char *msg), void *ctx)
7325b9c547cSRui Paulo {
7335b9c547cSRui Paulo 	conn->log_cb = cb;
7345b9c547cSRui Paulo 	conn->log_cb_ctx = ctx;
7355b9c547cSRui Paulo }
7365b9c547cSRui Paulo 
7375b9c547cSRui Paulo 
tlsv1_server_get_failed(struct tlsv1_server * conn)738*4bc52338SCy Schubert int tlsv1_server_get_failed(struct tlsv1_server *conn)
739*4bc52338SCy Schubert {
740*4bc52338SCy Schubert 	return conn->state == FAILED;
741*4bc52338SCy Schubert }
742*4bc52338SCy Schubert 
743*4bc52338SCy Schubert 
tlsv1_server_get_read_alerts(struct tlsv1_server * conn)744*4bc52338SCy Schubert int tlsv1_server_get_read_alerts(struct tlsv1_server *conn)
745*4bc52338SCy Schubert {
746*4bc52338SCy Schubert 	return conn->read_alerts;
747*4bc52338SCy Schubert }
748*4bc52338SCy Schubert 
749*4bc52338SCy Schubert 
tlsv1_server_get_write_alerts(struct tlsv1_server * conn)750*4bc52338SCy Schubert int tlsv1_server_get_write_alerts(struct tlsv1_server *conn)
751*4bc52338SCy Schubert {
752*4bc52338SCy Schubert 	return conn->write_alerts;
753*4bc52338SCy Schubert }
754*4bc52338SCy Schubert 
755*4bc52338SCy Schubert 
7565b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
tlsv1_server_set_test_flags(struct tlsv1_server * conn,u32 flags)7575b9c547cSRui Paulo void tlsv1_server_set_test_flags(struct tlsv1_server *conn, u32 flags)
7585b9c547cSRui Paulo {
7595b9c547cSRui Paulo 	conn->test_flags = flags;
7605b9c547cSRui Paulo }
7615b9c547cSRui Paulo 
7625b9c547cSRui Paulo 
7635b9c547cSRui Paulo static const u8 test_tls_prime15[1] = {
7645b9c547cSRui Paulo 	15
7655b9c547cSRui Paulo };
7665b9c547cSRui Paulo 
7675b9c547cSRui Paulo static const u8 test_tls_prime511b[64] = {
7685b9c547cSRui Paulo 	0x50, 0xfb, 0xf1, 0xae, 0x01, 0xf1, 0xfe, 0xe6,
7695b9c547cSRui Paulo 	0xe1, 0xae, 0xdc, 0x1e, 0xbe, 0xfb, 0x9e, 0x58,
7705b9c547cSRui Paulo 	0x9a, 0xd7, 0x54, 0x9d, 0x6b, 0xb3, 0x78, 0xe2,
7715b9c547cSRui Paulo 	0x39, 0x7f, 0x30, 0x01, 0x25, 0xa1, 0xf9, 0x7c,
7725b9c547cSRui Paulo 	0x55, 0x0e, 0xa1, 0x15, 0xcc, 0x36, 0x34, 0xbb,
7735b9c547cSRui Paulo 	0x6c, 0x8b, 0x64, 0x45, 0x15, 0x7f, 0xd3, 0xe7,
7745b9c547cSRui Paulo 	0x31, 0xc8, 0x8e, 0x56, 0x8e, 0x95, 0xdc, 0xea,
7755b9c547cSRui Paulo 	0x9e, 0xdf, 0xf7, 0x56, 0xdd, 0xb0, 0x34, 0xdb
7765b9c547cSRui Paulo };
7775b9c547cSRui Paulo 
7785b9c547cSRui Paulo static const u8 test_tls_prime767b[96] = {
7795b9c547cSRui Paulo 	0x4c, 0xdc, 0xb8, 0x21, 0x20, 0x9d, 0xe8, 0xa3,
7805b9c547cSRui Paulo 	0x53, 0xd9, 0x1c, 0x18, 0xc1, 0x3a, 0x58, 0x67,
7815b9c547cSRui Paulo 	0xa7, 0x85, 0xf9, 0x28, 0x9b, 0xce, 0xc0, 0xd1,
7825b9c547cSRui Paulo 	0x05, 0x84, 0x61, 0x97, 0xb2, 0x86, 0x1c, 0xd0,
7835b9c547cSRui Paulo 	0xd1, 0x96, 0x23, 0x29, 0x8c, 0xc5, 0x30, 0x68,
7845b9c547cSRui Paulo 	0x3e, 0xf9, 0x05, 0xba, 0x60, 0xeb, 0xdb, 0xee,
7855b9c547cSRui Paulo 	0x2d, 0xdf, 0x84, 0x65, 0x49, 0x87, 0x90, 0x2a,
7865b9c547cSRui Paulo 	0xc9, 0x8e, 0x34, 0x63, 0x6d, 0x9a, 0x2d, 0x32,
7875b9c547cSRui Paulo 	0x1c, 0x46, 0xd5, 0x4e, 0x20, 0x20, 0x90, 0xac,
7885b9c547cSRui Paulo 	0xd5, 0x48, 0x79, 0x99, 0x0c, 0xe6, 0xed, 0xbf,
7895b9c547cSRui Paulo 	0x79, 0xc2, 0x47, 0x50, 0x95, 0x38, 0x38, 0xbc,
7905b9c547cSRui Paulo 	0xde, 0xb0, 0xd2, 0xe8, 0x97, 0xcb, 0x22, 0xbb
7915b9c547cSRui Paulo };
7925b9c547cSRui Paulo 
7935b9c547cSRui Paulo static const u8 test_tls_prime58[128] = {
7945b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7955b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7965b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7975b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7985b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7995b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8005b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8015b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8025b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8035b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8045b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8055b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8065b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8075b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8085b9c547cSRui Paulo 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8095b9c547cSRui Paulo 	0x03, 0xc1, 0xba, 0xc8, 0x25, 0xbe, 0x2d, 0xf3
8105b9c547cSRui Paulo };
8115b9c547cSRui Paulo 
8125b9c547cSRui Paulo static const u8 test_tls_non_prime[] = {
8135b9c547cSRui Paulo 	/*
8145b9c547cSRui Paulo 	 * This is not a prime and the value has the following factors:
8155b9c547cSRui Paulo 	 * 13736783488716579923 * 16254860191773456563 * 18229434976173670763 *
8165b9c547cSRui Paulo 	 * 11112313018289079419 * 10260802278580253339 * 12394009491575311499 *
8175b9c547cSRui Paulo 	 * 12419059668711064739 * 14317973192687985827 * 10498605410533203179 *
8185b9c547cSRui Paulo 	 * 16338688760390249003 * 11128963991123878883 * 12990532258280301419 *
8195b9c547cSRui Paulo 	 * 3
8205b9c547cSRui Paulo 	 */
8215b9c547cSRui Paulo 	0x0C, 0x8C, 0x36, 0x9C, 0x6F, 0x71, 0x2E, 0xA7,
8225b9c547cSRui Paulo 	0xAB, 0x32, 0xD3, 0x0F, 0x68, 0x3D, 0xB2, 0x6D,
8235b9c547cSRui Paulo 	0x81, 0xDD, 0xC4, 0x84, 0x0D, 0x9C, 0x6E, 0x36,
8245b9c547cSRui Paulo 	0x29, 0x70, 0xF3, 0x1E, 0x9A, 0x42, 0x0B, 0x67,
8255b9c547cSRui Paulo 	0x82, 0x6B, 0xB1, 0xF2, 0xAF, 0x55, 0x28, 0xE7,
8265b9c547cSRui Paulo 	0xDB, 0x67, 0x6C, 0xF7, 0x6B, 0xAC, 0xAC, 0xE5,
8275b9c547cSRui Paulo 	0xF7, 0x9F, 0xD4, 0x63, 0x55, 0x70, 0x32, 0x7C,
8285b9c547cSRui Paulo 	0x70, 0xFB, 0xAF, 0xB8, 0xEB, 0x37, 0xCF, 0x3F,
8295b9c547cSRui Paulo 	0xFE, 0x94, 0x73, 0xF9, 0x7A, 0xC7, 0x12, 0x2E,
8305b9c547cSRui Paulo 	0x9B, 0xB4, 0x7D, 0x08, 0x60, 0x83, 0x43, 0x52,
8315b9c547cSRui Paulo 	0x83, 0x1E, 0xA5, 0xFC, 0xFA, 0x87, 0x12, 0xF4,
8325b9c547cSRui Paulo 	0x64, 0xE2, 0xCE, 0x71, 0x17, 0x72, 0xB6, 0xAB
8335b9c547cSRui Paulo };
8345b9c547cSRui Paulo 
8355b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
8365b9c547cSRui Paulo 
8375b9c547cSRui Paulo 
tlsv1_server_get_dh_p(struct tlsv1_server * conn,const u8 ** dh_p,size_t * dh_p_len)8385b9c547cSRui Paulo void tlsv1_server_get_dh_p(struct tlsv1_server *conn, const u8 **dh_p,
8395b9c547cSRui Paulo 			   size_t *dh_p_len)
8405b9c547cSRui Paulo {
8415b9c547cSRui Paulo 	*dh_p = conn->cred->dh_p;
8425b9c547cSRui Paulo 	*dh_p_len = conn->cred->dh_p_len;
8435b9c547cSRui Paulo 
8445b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS
8455b9c547cSRui Paulo 	if (conn->test_flags & TLS_DHE_PRIME_511B) {
8465b9c547cSRui Paulo 		tlsv1_server_log(conn, "TESTING: Use short 511-bit prime with DHE");
8475b9c547cSRui Paulo 		*dh_p = test_tls_prime511b;
8485b9c547cSRui Paulo 		*dh_p_len = sizeof(test_tls_prime511b);
8495b9c547cSRui Paulo 	} else if (conn->test_flags & TLS_DHE_PRIME_767B) {
8505b9c547cSRui Paulo 		tlsv1_server_log(conn, "TESTING: Use short 767-bit prime with DHE");
8515b9c547cSRui Paulo 		*dh_p = test_tls_prime767b;
8525b9c547cSRui Paulo 		*dh_p_len = sizeof(test_tls_prime767b);
8535b9c547cSRui Paulo 	} else if (conn->test_flags & TLS_DHE_PRIME_15) {
8545b9c547cSRui Paulo 		tlsv1_server_log(conn, "TESTING: Use bogus 15 \"prime\" with DHE");
8555b9c547cSRui Paulo 		*dh_p = test_tls_prime15;
8565b9c547cSRui Paulo 		*dh_p_len = sizeof(test_tls_prime15);
8575b9c547cSRui Paulo 	} else if (conn->test_flags & TLS_DHE_PRIME_58B) {
8585b9c547cSRui Paulo 		tlsv1_server_log(conn, "TESTING: Use short 58-bit prime in long container with DHE");
8595b9c547cSRui Paulo 		*dh_p = test_tls_prime58;
8605b9c547cSRui Paulo 		*dh_p_len = sizeof(test_tls_prime58);
8615b9c547cSRui Paulo 	} else if (conn->test_flags & TLS_DHE_NON_PRIME) {
8625b9c547cSRui Paulo 		tlsv1_server_log(conn, "TESTING: Use claim non-prime as the DHE prime");
8635b9c547cSRui Paulo 		*dh_p = test_tls_non_prime;
8645b9c547cSRui Paulo 		*dh_p_len = sizeof(test_tls_non_prime);
8655b9c547cSRui Paulo 	}
8665b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */
8675b9c547cSRui Paulo }
868