xref: /freebsd/contrib/wpa/src/tls/tlsv1_client.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
139beb93cSSam Leffler /*
2f05cddf9SRui Paulo  * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
34bc52338SCy 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"
14780fb4a2SCy Schubert #include "x509v3.h"
1539beb93cSSam Leffler #include "tlsv1_common.h"
1639beb93cSSam Leffler #include "tlsv1_record.h"
1739beb93cSSam Leffler #include "tlsv1_client.h"
1839beb93cSSam Leffler #include "tlsv1_client_i.h"
1939beb93cSSam Leffler 
2039beb93cSSam Leffler /* TODO:
2139beb93cSSam Leffler  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
2239beb93cSSam Leffler  */
2339beb93cSSam Leffler 
2439beb93cSSam Leffler 
tls_alert(struct tlsv1_client * conn,u8 level,u8 description)2539beb93cSSam Leffler void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
2639beb93cSSam Leffler {
2739beb93cSSam Leffler 	conn->alert_level = level;
2839beb93cSSam Leffler 	conn->alert_description = description;
2939beb93cSSam Leffler }
3039beb93cSSam Leffler 
3139beb93cSSam Leffler 
tlsv1_client_free_dh(struct tlsv1_client * conn)3239beb93cSSam Leffler void tlsv1_client_free_dh(struct tlsv1_client *conn)
3339beb93cSSam Leffler {
3439beb93cSSam Leffler 	os_free(conn->dh_p);
3539beb93cSSam Leffler 	os_free(conn->dh_g);
3639beb93cSSam Leffler 	os_free(conn->dh_ys);
3739beb93cSSam Leffler 	conn->dh_p = conn->dh_g = conn->dh_ys = NULL;
3839beb93cSSam Leffler }
3939beb93cSSam Leffler 
4039beb93cSSam Leffler 
tls_client_highest_ver(struct tlsv1_client * conn)41*c1d255d3SCy Schubert u16 tls_client_highest_ver(struct tlsv1_client *conn)
4239beb93cSSam Leffler {
43*c1d255d3SCy Schubert 	u16 tls_version = TLS_VERSION;
44*c1d255d3SCy Schubert 
45*c1d255d3SCy Schubert 	/* Pick the highest locally enabled TLS version */
46*c1d255d3SCy Schubert #ifdef CONFIG_TLSV12
47*c1d255d3SCy Schubert 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
48*c1d255d3SCy Schubert 	    tls_version == TLS_VERSION_1_2)
49*c1d255d3SCy Schubert 		tls_version = TLS_VERSION_1_1;
50*c1d255d3SCy Schubert #endif /* CONFIG_TLSV12 */
51*c1d255d3SCy Schubert #ifdef CONFIG_TLSV11
52*c1d255d3SCy Schubert 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
53*c1d255d3SCy Schubert 	    tls_version == TLS_VERSION_1_1)
54*c1d255d3SCy Schubert 		tls_version = TLS_VERSION_1;
55*c1d255d3SCy Schubert #endif /* CONFIG_TLSV11 */
56*c1d255d3SCy Schubert 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
57*c1d255d3SCy Schubert 	    tls_version == TLS_VERSION_1)
58*c1d255d3SCy Schubert 		return 0;
59*c1d255d3SCy Schubert 
60*c1d255d3SCy Schubert 	return tls_version;
61*c1d255d3SCy Schubert }
62*c1d255d3SCy Schubert 
63*c1d255d3SCy Schubert 
tls_derive_pre_master_secret(struct tlsv1_client * conn,u8 * pre_master_secret)64*c1d255d3SCy Schubert int tls_derive_pre_master_secret(struct tlsv1_client *conn,
65*c1d255d3SCy Schubert 				 u8 *pre_master_secret)
66*c1d255d3SCy Schubert {
67*c1d255d3SCy Schubert 	WPA_PUT_BE16(pre_master_secret, tls_client_highest_ver(conn));
6839beb93cSSam Leffler 	if (os_get_random(pre_master_secret + 2,
6939beb93cSSam Leffler 			  TLS_PRE_MASTER_SECRET_LEN - 2))
7039beb93cSSam Leffler 		return -1;
7139beb93cSSam Leffler 	return 0;
7239beb93cSSam Leffler }
7339beb93cSSam Leffler 
7439beb93cSSam Leffler 
tls_derive_keys(struct tlsv1_client * conn,const u8 * pre_master_secret,size_t pre_master_secret_len)7539beb93cSSam Leffler int tls_derive_keys(struct tlsv1_client *conn,
7639beb93cSSam Leffler 		    const u8 *pre_master_secret, size_t pre_master_secret_len)
7739beb93cSSam Leffler {
7839beb93cSSam Leffler 	u8 seed[2 * TLS_RANDOM_LEN];
7939beb93cSSam Leffler 	u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
8039beb93cSSam Leffler 	u8 *pos;
8139beb93cSSam Leffler 	size_t key_block_len;
8239beb93cSSam Leffler 
8339beb93cSSam Leffler 	if (pre_master_secret) {
8439beb93cSSam Leffler 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
8539beb93cSSam Leffler 				pre_master_secret, pre_master_secret_len);
8639beb93cSSam Leffler 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
8739beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
8839beb93cSSam Leffler 			  TLS_RANDOM_LEN);
89f05cddf9SRui Paulo 		if (tls_prf(conn->rl.tls_version,
90f05cddf9SRui Paulo 			    pre_master_secret, pre_master_secret_len,
9139beb93cSSam Leffler 			    "master secret", seed, 2 * TLS_RANDOM_LEN,
9239beb93cSSam Leffler 			    conn->master_secret, TLS_MASTER_SECRET_LEN)) {
9339beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
9439beb93cSSam Leffler 				   "master_secret");
9539beb93cSSam Leffler 			return -1;
9639beb93cSSam Leffler 		}
9739beb93cSSam Leffler 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
9839beb93cSSam Leffler 				conn->master_secret, TLS_MASTER_SECRET_LEN);
9939beb93cSSam Leffler 	}
10039beb93cSSam Leffler 
10139beb93cSSam Leffler 	os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
10239beb93cSSam Leffler 	os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
103f05cddf9SRui Paulo 	key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len);
104f05cddf9SRui Paulo 	if (conn->rl.tls_version == TLS_VERSION_1)
105f05cddf9SRui Paulo 		key_block_len += 2 * conn->rl.iv_size;
106f05cddf9SRui Paulo 	if (tls_prf(conn->rl.tls_version,
107f05cddf9SRui Paulo 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
10839beb93cSSam Leffler 		    "key expansion", seed, 2 * TLS_RANDOM_LEN,
10939beb93cSSam Leffler 		    key_block, key_block_len)) {
11039beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
11139beb93cSSam Leffler 		return -1;
11239beb93cSSam Leffler 	}
11339beb93cSSam Leffler 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
11439beb93cSSam Leffler 			key_block, key_block_len);
11539beb93cSSam Leffler 
11639beb93cSSam Leffler 	pos = key_block;
11739beb93cSSam Leffler 
11839beb93cSSam Leffler 	/* client_write_MAC_secret */
11939beb93cSSam Leffler 	os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
12039beb93cSSam Leffler 	pos += conn->rl.hash_size;
12139beb93cSSam Leffler 	/* server_write_MAC_secret */
12239beb93cSSam Leffler 	os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
12339beb93cSSam Leffler 	pos += conn->rl.hash_size;
12439beb93cSSam Leffler 
12539beb93cSSam Leffler 	/* client_write_key */
12639beb93cSSam Leffler 	os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
12739beb93cSSam Leffler 	pos += conn->rl.key_material_len;
12839beb93cSSam Leffler 	/* server_write_key */
12939beb93cSSam Leffler 	os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
13039beb93cSSam Leffler 	pos += conn->rl.key_material_len;
13139beb93cSSam Leffler 
132f05cddf9SRui Paulo 	if (conn->rl.tls_version == TLS_VERSION_1) {
13339beb93cSSam Leffler 		/* client_write_IV */
13439beb93cSSam Leffler 		os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
13539beb93cSSam Leffler 		pos += conn->rl.iv_size;
13639beb93cSSam Leffler 		/* server_write_IV */
13739beb93cSSam Leffler 		os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
138f05cddf9SRui Paulo 	} else {
139f05cddf9SRui Paulo 		/*
140f05cddf9SRui Paulo 		 * Use IV field to set the mask value for TLS v1.1. A fixed
141f05cddf9SRui Paulo 		 * mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block
142f05cddf9SRui Paulo 		 * Cipher option 2a.
143f05cddf9SRui Paulo 		 */
144f05cddf9SRui Paulo 		os_memset(conn->rl.write_iv, 0, conn->rl.iv_size);
145f05cddf9SRui Paulo 	}
14639beb93cSSam Leffler 
14739beb93cSSam Leffler 	return 0;
14839beb93cSSam Leffler }
14939beb93cSSam Leffler 
15039beb93cSSam Leffler 
15139beb93cSSam Leffler /**
15239beb93cSSam Leffler  * tlsv1_client_handshake - Process TLS handshake
15339beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
15439beb93cSSam Leffler  * @in_data: Input data from TLS peer
15539beb93cSSam Leffler  * @in_len: Input data length
15639beb93cSSam Leffler  * @out_len: Length of the output buffer.
15739beb93cSSam Leffler  * @appl_data: Pointer to application data pointer, or %NULL if dropped
15839beb93cSSam Leffler  * @appl_data_len: Pointer to variable that is set to appl_data length
159f05cddf9SRui Paulo  * @need_more_data: Set to 1 if more data would be needed to complete
160f05cddf9SRui Paulo  *	processing
16139beb93cSSam Leffler  * Returns: Pointer to output data, %NULL on failure
16239beb93cSSam Leffler  */
tlsv1_client_handshake(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,size_t * out_len,u8 ** appl_data,size_t * appl_data_len,int * need_more_data)16339beb93cSSam Leffler u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
16439beb93cSSam Leffler 			    const u8 *in_data, size_t in_len,
16539beb93cSSam Leffler 			    size_t *out_len, u8 **appl_data,
166f05cddf9SRui Paulo 			    size_t *appl_data_len, int *need_more_data)
16739beb93cSSam Leffler {
16839beb93cSSam Leffler 	const u8 *pos, *end;
169f05cddf9SRui Paulo 	u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct;
17039beb93cSSam Leffler 	size_t in_msg_len;
17139beb93cSSam Leffler 	int no_appl_data;
172f05cddf9SRui Paulo 	int used;
173f05cddf9SRui Paulo 
174f05cddf9SRui Paulo 	if (need_more_data)
175f05cddf9SRui Paulo 		*need_more_data = 0;
17639beb93cSSam Leffler 
17739beb93cSSam Leffler 	if (conn->state == CLIENT_HELLO) {
17839beb93cSSam Leffler 		if (in_len)
17939beb93cSSam Leffler 			return NULL;
18039beb93cSSam Leffler 		return tls_send_client_hello(conn, out_len);
18139beb93cSSam Leffler 	}
18239beb93cSSam Leffler 
183f05cddf9SRui Paulo 	if (conn->partial_input) {
184f05cddf9SRui Paulo 		if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
185f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
186f05cddf9SRui Paulo 				   "memory for pending record");
187f05cddf9SRui Paulo 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
188f05cddf9SRui Paulo 				  TLS_ALERT_INTERNAL_ERROR);
189f05cddf9SRui Paulo 			goto failed;
190f05cddf9SRui Paulo 		}
191f05cddf9SRui Paulo 		wpabuf_put_data(conn->partial_input, in_data, in_len);
192f05cddf9SRui Paulo 		in_data = wpabuf_head(conn->partial_input);
193f05cddf9SRui Paulo 		in_len = wpabuf_len(conn->partial_input);
194f05cddf9SRui Paulo 	}
195f05cddf9SRui Paulo 
19639beb93cSSam Leffler 	if (in_data == NULL || in_len == 0)
19739beb93cSSam Leffler 		return NULL;
19839beb93cSSam Leffler 
19939beb93cSSam Leffler 	pos = in_data;
20039beb93cSSam Leffler 	end = in_data + in_len;
20139beb93cSSam Leffler 	in_msg = os_malloc(in_len);
20239beb93cSSam Leffler 	if (in_msg == NULL)
20339beb93cSSam Leffler 		return NULL;
20439beb93cSSam Leffler 
20539beb93cSSam Leffler 	/* Each received packet may include multiple records */
20639beb93cSSam Leffler 	while (pos < end) {
20739beb93cSSam Leffler 		in_msg_len = in_len;
208f05cddf9SRui Paulo 		used = tlsv1_record_receive(&conn->rl, pos, end - pos,
209f05cddf9SRui Paulo 					    in_msg, &in_msg_len, &alert);
210f05cddf9SRui Paulo 		if (used < 0) {
21139beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
21239beb93cSSam Leffler 				   "record failed");
21339beb93cSSam Leffler 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
21439beb93cSSam Leffler 			goto failed;
21539beb93cSSam Leffler 		}
216f05cddf9SRui Paulo 		if (used == 0) {
217f05cddf9SRui Paulo 			struct wpabuf *partial;
218f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
219f05cddf9SRui Paulo 			partial = wpabuf_alloc_copy(pos, end - pos);
220f05cddf9SRui Paulo 			wpabuf_free(conn->partial_input);
221f05cddf9SRui Paulo 			conn->partial_input = partial;
222f05cddf9SRui Paulo 			if (conn->partial_input == NULL) {
223f05cddf9SRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
224f05cddf9SRui Paulo 					   "allocate memory for pending "
225f05cddf9SRui Paulo 					   "record");
226f05cddf9SRui Paulo 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
227f05cddf9SRui Paulo 					  TLS_ALERT_INTERNAL_ERROR);
228f05cddf9SRui Paulo 				goto failed;
229f05cddf9SRui Paulo 			}
230f05cddf9SRui Paulo 			os_free(in_msg);
231f05cddf9SRui Paulo 			if (need_more_data)
232f05cddf9SRui Paulo 				*need_more_data = 1;
233f05cddf9SRui Paulo 			return NULL;
234f05cddf9SRui Paulo 		}
23539beb93cSSam Leffler 		ct = pos[0];
23639beb93cSSam Leffler 
23739beb93cSSam Leffler 		in_pos = in_msg;
23839beb93cSSam Leffler 		in_end = in_msg + in_msg_len;
23939beb93cSSam Leffler 
24039beb93cSSam Leffler 		/* Each received record may include multiple messages of the
24139beb93cSSam Leffler 		 * same ContentType. */
24239beb93cSSam Leffler 		while (in_pos < in_end) {
24339beb93cSSam Leffler 			in_msg_len = in_end - in_pos;
24439beb93cSSam Leffler 			if (tlsv1_client_process_handshake(conn, ct, in_pos,
24539beb93cSSam Leffler 							   &in_msg_len,
24639beb93cSSam Leffler 							   appl_data,
24739beb93cSSam Leffler 							   appl_data_len) < 0)
24839beb93cSSam Leffler 				goto failed;
24939beb93cSSam Leffler 			in_pos += in_msg_len;
25039beb93cSSam Leffler 		}
25139beb93cSSam Leffler 
252f05cddf9SRui Paulo 		pos += used;
25339beb93cSSam Leffler 	}
25439beb93cSSam Leffler 
25539beb93cSSam Leffler 	os_free(in_msg);
25639beb93cSSam Leffler 	in_msg = NULL;
25739beb93cSSam Leffler 
25839beb93cSSam Leffler 	no_appl_data = appl_data == NULL || *appl_data == NULL;
25939beb93cSSam Leffler 	msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data);
26039beb93cSSam Leffler 
26139beb93cSSam Leffler failed:
26239beb93cSSam Leffler 	os_free(in_msg);
26339beb93cSSam Leffler 	if (conn->alert_level) {
264f05cddf9SRui Paulo 		wpabuf_free(conn->partial_input);
265f05cddf9SRui Paulo 		conn->partial_input = NULL;
26639beb93cSSam Leffler 		conn->state = FAILED;
26739beb93cSSam Leffler 		os_free(msg);
26839beb93cSSam Leffler 		msg = tlsv1_client_send_alert(conn, conn->alert_level,
26939beb93cSSam Leffler 					      conn->alert_description,
27039beb93cSSam Leffler 					      out_len);
27139beb93cSSam Leffler 	} else if (msg == NULL) {
27239beb93cSSam Leffler 		msg = os_zalloc(1);
27339beb93cSSam Leffler 		*out_len = 0;
27439beb93cSSam Leffler 	}
27539beb93cSSam Leffler 
276f05cddf9SRui Paulo 	if (need_more_data == NULL || !(*need_more_data)) {
277f05cddf9SRui Paulo 		wpabuf_free(conn->partial_input);
278f05cddf9SRui Paulo 		conn->partial_input = NULL;
279f05cddf9SRui Paulo 	}
280f05cddf9SRui Paulo 
28139beb93cSSam Leffler 	return msg;
28239beb93cSSam Leffler }
28339beb93cSSam Leffler 
28439beb93cSSam Leffler 
28539beb93cSSam Leffler /**
28639beb93cSSam Leffler  * tlsv1_client_encrypt - Encrypt data into TLS tunnel
28739beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
28839beb93cSSam Leffler  * @in_data: Pointer to plaintext data to be encrypted
28939beb93cSSam Leffler  * @in_len: Input buffer length
29039beb93cSSam Leffler  * @out_data: Pointer to output buffer (encrypted TLS data)
29139beb93cSSam Leffler  * @out_len: Maximum out_data length
29239beb93cSSam Leffler  * Returns: Number of bytes written to out_data, -1 on failure
29339beb93cSSam Leffler  *
29439beb93cSSam Leffler  * This function is used after TLS handshake has been completed successfully to
29539beb93cSSam Leffler  * send data in the encrypted tunnel.
29639beb93cSSam Leffler  */
tlsv1_client_encrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)29739beb93cSSam Leffler int tlsv1_client_encrypt(struct tlsv1_client *conn,
29839beb93cSSam Leffler 			 const u8 *in_data, size_t in_len,
29939beb93cSSam Leffler 			 u8 *out_data, size_t out_len)
30039beb93cSSam Leffler {
30139beb93cSSam Leffler 	size_t rlen;
30239beb93cSSam Leffler 
30339beb93cSSam Leffler 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
30439beb93cSSam Leffler 			in_data, in_len);
30539beb93cSSam Leffler 
30639beb93cSSam Leffler 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
307f05cddf9SRui Paulo 			      out_data, out_len, in_data, in_len, &rlen) < 0) {
30839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
30939beb93cSSam Leffler 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
31039beb93cSSam Leffler 			  TLS_ALERT_INTERNAL_ERROR);
31139beb93cSSam Leffler 		return -1;
31239beb93cSSam Leffler 	}
31339beb93cSSam Leffler 
31439beb93cSSam Leffler 	return rlen;
31539beb93cSSam Leffler }
31639beb93cSSam Leffler 
31739beb93cSSam Leffler 
31839beb93cSSam Leffler /**
31939beb93cSSam Leffler  * tlsv1_client_decrypt - Decrypt data from TLS tunnel
32039beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
32139beb93cSSam Leffler  * @in_data: Pointer to input buffer (encrypted TLS data)
32239beb93cSSam Leffler  * @in_len: Input buffer length
323f05cddf9SRui Paulo  * @need_more_data: Set to 1 if more data would be needed to complete
324f05cddf9SRui Paulo  *	processing
325f05cddf9SRui Paulo  * Returns: Decrypted data or %NULL on failure
32639beb93cSSam Leffler  *
32739beb93cSSam Leffler  * This function is used after TLS handshake has been completed successfully to
32839beb93cSSam Leffler  * receive data from the encrypted tunnel.
32939beb93cSSam Leffler  */
tlsv1_client_decrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,int * need_more_data)330f05cddf9SRui Paulo struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn,
33139beb93cSSam Leffler 				     const u8 *in_data, size_t in_len,
332f05cddf9SRui Paulo 				     int *need_more_data)
33339beb93cSSam Leffler {
33439beb93cSSam Leffler 	const u8 *in_end, *pos;
335f05cddf9SRui Paulo 	int used;
336f05cddf9SRui Paulo 	u8 alert, *out_pos, ct;
33739beb93cSSam Leffler 	size_t olen;
338f05cddf9SRui Paulo 	struct wpabuf *buf = NULL;
339f05cddf9SRui Paulo 
340f05cddf9SRui Paulo 	if (need_more_data)
341f05cddf9SRui Paulo 		*need_more_data = 0;
342f05cddf9SRui Paulo 
343f05cddf9SRui Paulo 	if (conn->partial_input) {
344f05cddf9SRui Paulo 		if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
345f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
346f05cddf9SRui Paulo 				   "memory for pending record");
347f05cddf9SRui Paulo 			alert = TLS_ALERT_INTERNAL_ERROR;
348f05cddf9SRui Paulo 			goto fail;
349f05cddf9SRui Paulo 		}
350f05cddf9SRui Paulo 		wpabuf_put_data(conn->partial_input, in_data, in_len);
351f05cddf9SRui Paulo 		in_data = wpabuf_head(conn->partial_input);
352f05cddf9SRui Paulo 		in_len = wpabuf_len(conn->partial_input);
353f05cddf9SRui Paulo 	}
35439beb93cSSam Leffler 
35539beb93cSSam Leffler 	pos = in_data;
35639beb93cSSam Leffler 	in_end = in_data + in_len;
35739beb93cSSam Leffler 
35839beb93cSSam Leffler 	while (pos < in_end) {
359f05cddf9SRui Paulo 		ct = pos[0];
360f05cddf9SRui Paulo 		if (wpabuf_resize(&buf, in_end - pos) < 0) {
361f05cddf9SRui Paulo 			alert = TLS_ALERT_INTERNAL_ERROR;
362f05cddf9SRui Paulo 			goto fail;
36339beb93cSSam Leffler 		}
364f05cddf9SRui Paulo 		out_pos = wpabuf_put(buf, 0);
365f05cddf9SRui Paulo 		olen = wpabuf_tailroom(buf);
366f05cddf9SRui Paulo 		used = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
36739beb93cSSam Leffler 					    out_pos, &olen, &alert);
368f05cddf9SRui Paulo 		if (used < 0) {
36939beb93cSSam Leffler 			wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
37039beb93cSSam Leffler 				   "failed");
371f05cddf9SRui Paulo 			goto fail;
372f05cddf9SRui Paulo 		}
373f05cddf9SRui Paulo 		if (used == 0) {
374f05cddf9SRui Paulo 			struct wpabuf *partial;
375f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
376f05cddf9SRui Paulo 			partial = wpabuf_alloc_copy(pos, in_end - pos);
377f05cddf9SRui Paulo 			wpabuf_free(conn->partial_input);
378f05cddf9SRui Paulo 			conn->partial_input = partial;
379f05cddf9SRui Paulo 			if (conn->partial_input == NULL) {
380f05cddf9SRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
381f05cddf9SRui Paulo 					   "allocate memory for pending "
382f05cddf9SRui Paulo 					   "record");
383f05cddf9SRui Paulo 				alert = TLS_ALERT_INTERNAL_ERROR;
384f05cddf9SRui Paulo 				goto fail;
385f05cddf9SRui Paulo 			}
386f05cddf9SRui Paulo 			if (need_more_data)
387f05cddf9SRui Paulo 				*need_more_data = 1;
388f05cddf9SRui Paulo 			return buf;
389f05cddf9SRui Paulo 		}
390f05cddf9SRui Paulo 
391f05cddf9SRui Paulo 		if (ct == TLS_CONTENT_TYPE_ALERT) {
392f05cddf9SRui Paulo 			if (olen < 2) {
393f05cddf9SRui Paulo 				wpa_printf(MSG_DEBUG, "TLSv1: Alert "
394f05cddf9SRui Paulo 					   "underflow");
395f05cddf9SRui Paulo 				alert = TLS_ALERT_DECODE_ERROR;
396f05cddf9SRui Paulo 				goto fail;
397f05cddf9SRui Paulo 			}
398f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
399f05cddf9SRui Paulo 				   out_pos[0], out_pos[1]);
400f05cddf9SRui Paulo 			if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) {
401f05cddf9SRui Paulo 				/* Continue processing */
402f05cddf9SRui Paulo 				pos += used;
403f05cddf9SRui Paulo 				continue;
404f05cddf9SRui Paulo 			}
405f05cddf9SRui Paulo 
406f05cddf9SRui Paulo 			alert = out_pos[1];
407f05cddf9SRui Paulo 			goto fail;
408f05cddf9SRui Paulo 		}
409f05cddf9SRui Paulo 
410f05cddf9SRui Paulo 		if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
411f05cddf9SRui Paulo 			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
412f05cddf9SRui Paulo 				   "0x%x when decrypting application data",
413f05cddf9SRui Paulo 				   pos[0]);
414f05cddf9SRui Paulo 			alert = TLS_ALERT_UNEXPECTED_MESSAGE;
415f05cddf9SRui Paulo 			goto fail;
416f05cddf9SRui Paulo 		}
417f05cddf9SRui Paulo 
418f05cddf9SRui Paulo 		wpabuf_put(buf, olen);
419f05cddf9SRui Paulo 
420f05cddf9SRui Paulo 		pos += used;
421f05cddf9SRui Paulo 	}
422f05cddf9SRui Paulo 
423f05cddf9SRui Paulo 	wpabuf_free(conn->partial_input);
424f05cddf9SRui Paulo 	conn->partial_input = NULL;
425f05cddf9SRui Paulo 	return buf;
426f05cddf9SRui Paulo 
427f05cddf9SRui Paulo fail:
428f05cddf9SRui Paulo 	wpabuf_free(buf);
429f05cddf9SRui Paulo 	wpabuf_free(conn->partial_input);
430f05cddf9SRui Paulo 	conn->partial_input = NULL;
43139beb93cSSam Leffler 	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
432f05cddf9SRui Paulo 	return NULL;
43339beb93cSSam Leffler }
43439beb93cSSam Leffler 
43539beb93cSSam Leffler 
43639beb93cSSam Leffler /**
43739beb93cSSam Leffler  * tlsv1_client_global_init - Initialize TLSv1 client
43839beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
43939beb93cSSam Leffler  *
44039beb93cSSam Leffler  * This function must be called before using any other TLSv1 client functions.
44139beb93cSSam Leffler  */
tlsv1_client_global_init(void)44239beb93cSSam Leffler int tlsv1_client_global_init(void)
44339beb93cSSam Leffler {
44439beb93cSSam Leffler 	return crypto_global_init();
44539beb93cSSam Leffler }
44639beb93cSSam Leffler 
44739beb93cSSam Leffler 
44839beb93cSSam Leffler /**
44939beb93cSSam Leffler  * tlsv1_client_global_deinit - Deinitialize TLSv1 client
45039beb93cSSam Leffler  *
45139beb93cSSam Leffler  * This function can be used to deinitialize the TLSv1 client that was
45239beb93cSSam Leffler  * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions
45339beb93cSSam Leffler  * can be called after this before calling tlsv1_client_global_init() again.
45439beb93cSSam Leffler  */
tlsv1_client_global_deinit(void)45539beb93cSSam Leffler void tlsv1_client_global_deinit(void)
45639beb93cSSam Leffler {
45739beb93cSSam Leffler 	crypto_global_deinit();
45839beb93cSSam Leffler }
45939beb93cSSam Leffler 
46039beb93cSSam Leffler 
46139beb93cSSam Leffler /**
46239beb93cSSam Leffler  * tlsv1_client_init - Initialize TLSv1 client connection
46339beb93cSSam Leffler  * Returns: Pointer to TLSv1 client connection data or %NULL on failure
46439beb93cSSam Leffler  */
tlsv1_client_init(void)46539beb93cSSam Leffler struct tlsv1_client * tlsv1_client_init(void)
46639beb93cSSam Leffler {
46739beb93cSSam Leffler 	struct tlsv1_client *conn;
46839beb93cSSam Leffler 	size_t count;
46939beb93cSSam Leffler 	u16 *suites;
47039beb93cSSam Leffler 
47139beb93cSSam Leffler 	conn = os_zalloc(sizeof(*conn));
47239beb93cSSam Leffler 	if (conn == NULL)
47339beb93cSSam Leffler 		return NULL;
47439beb93cSSam Leffler 
47539beb93cSSam Leffler 	conn->state = CLIENT_HELLO;
47639beb93cSSam Leffler 
47739beb93cSSam Leffler 	if (tls_verify_hash_init(&conn->verify) < 0) {
47839beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
47939beb93cSSam Leffler 			   "hash");
48039beb93cSSam Leffler 		os_free(conn);
48139beb93cSSam Leffler 		return NULL;
48239beb93cSSam Leffler 	}
48339beb93cSSam Leffler 
48439beb93cSSam Leffler 	count = 0;
48539beb93cSSam Leffler 	suites = conn->cipher_suites;
4865b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
487f05cddf9SRui Paulo 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
4885b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
48939beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
4905b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
491f05cddf9SRui Paulo 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
4925b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
49339beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
4945b9c547cSRui Paulo 	suites[count++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
49539beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
49639beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
49739beb93cSSam Leffler 	suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
49839beb93cSSam Leffler 	conn->num_cipher_suites = count;
49939beb93cSSam Leffler 
500f05cddf9SRui Paulo 	conn->rl.tls_version = TLS_VERSION;
501f05cddf9SRui Paulo 
50239beb93cSSam Leffler 	return conn;
50339beb93cSSam Leffler }
50439beb93cSSam Leffler 
50539beb93cSSam Leffler 
50639beb93cSSam Leffler /**
50739beb93cSSam Leffler  * tlsv1_client_deinit - Deinitialize TLSv1 client connection
50839beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
50939beb93cSSam Leffler  */
tlsv1_client_deinit(struct tlsv1_client * conn)51039beb93cSSam Leffler void tlsv1_client_deinit(struct tlsv1_client *conn)
51139beb93cSSam Leffler {
51239beb93cSSam Leffler 	crypto_public_key_free(conn->server_rsa_key);
51339beb93cSSam Leffler 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
51439beb93cSSam Leffler 	tlsv1_record_change_write_cipher(&conn->rl);
51539beb93cSSam Leffler 	tlsv1_record_change_read_cipher(&conn->rl);
51639beb93cSSam Leffler 	tls_verify_hash_free(&conn->verify);
51739beb93cSSam Leffler 	os_free(conn->client_hello_ext);
51839beb93cSSam Leffler 	tlsv1_client_free_dh(conn);
51939beb93cSSam Leffler 	tlsv1_cred_free(conn->cred);
520f05cddf9SRui Paulo 	wpabuf_free(conn->partial_input);
521780fb4a2SCy Schubert 	x509_certificate_chain_free(conn->server_cert);
52239beb93cSSam Leffler 	os_free(conn);
52339beb93cSSam Leffler }
52439beb93cSSam Leffler 
52539beb93cSSam Leffler 
52639beb93cSSam Leffler /**
52739beb93cSSam Leffler  * tlsv1_client_established - Check whether connection has been established
52839beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
52939beb93cSSam Leffler  * Returns: 1 if connection is established, 0 if not
53039beb93cSSam Leffler  */
tlsv1_client_established(struct tlsv1_client * conn)53139beb93cSSam Leffler int tlsv1_client_established(struct tlsv1_client *conn)
53239beb93cSSam Leffler {
53339beb93cSSam Leffler 	return conn->state == ESTABLISHED;
53439beb93cSSam Leffler }
53539beb93cSSam Leffler 
53639beb93cSSam Leffler 
53739beb93cSSam Leffler /**
53839beb93cSSam Leffler  * tlsv1_client_prf - Use TLS-PRF to derive keying material
53939beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
54039beb93cSSam Leffler  * @label: Label (e.g., description of the key) for PRF
5414bc52338SCy Schubert  * @context: Optional extra upper-layer context (max len 2^16)
5424bc52338SCy Schubert  * @context_len: The length of the context value
54339beb93cSSam Leffler  * @server_random_first: seed is 0 = client_random|server_random,
54439beb93cSSam Leffler  * 1 = server_random|client_random
54539beb93cSSam Leffler  * @out: Buffer for output data from TLS-PRF
54639beb93cSSam Leffler  * @out_len: Length of the output buffer
54739beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
54839beb93cSSam Leffler  */
tlsv1_client_prf(struct tlsv1_client * conn,const char * label,const u8 * context,size_t context_len,int server_random_first,u8 * out,size_t out_len)54939beb93cSSam Leffler int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
5504bc52338SCy Schubert 		     const u8 *context, size_t context_len,
55139beb93cSSam Leffler 		     int server_random_first, u8 *out, size_t out_len)
55239beb93cSSam Leffler {
5534bc52338SCy Schubert 	u8 *seed, *pos;
5544bc52338SCy Schubert 	size_t seed_len = 2 * TLS_RANDOM_LEN;
5554bc52338SCy Schubert 	int res;
55639beb93cSSam Leffler 
55739beb93cSSam Leffler 	if (conn->state != ESTABLISHED)
55839beb93cSSam Leffler 		return -1;
55939beb93cSSam Leffler 
5604bc52338SCy Schubert 	if (context_len > 65535)
5614bc52338SCy Schubert 		return -1;
5624bc52338SCy Schubert 
5634bc52338SCy Schubert 	if (context)
5644bc52338SCy Schubert 		seed_len += 2 + context_len;
5654bc52338SCy Schubert 
5664bc52338SCy Schubert 	seed = os_malloc(seed_len);
5674bc52338SCy Schubert 	if (!seed)
5684bc52338SCy Schubert 		return -1;
5694bc52338SCy Schubert 
57039beb93cSSam Leffler 	if (server_random_first) {
57139beb93cSSam Leffler 		os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
57239beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
57339beb93cSSam Leffler 			  TLS_RANDOM_LEN);
57439beb93cSSam Leffler 	} else {
57539beb93cSSam Leffler 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
57639beb93cSSam Leffler 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
57739beb93cSSam Leffler 			  TLS_RANDOM_LEN);
57839beb93cSSam Leffler 	}
57939beb93cSSam Leffler 
5804bc52338SCy Schubert 	if (context) {
5814bc52338SCy Schubert 		pos = seed + 2 * TLS_RANDOM_LEN;
5824bc52338SCy Schubert 		WPA_PUT_BE16(pos, context_len);
5834bc52338SCy Schubert 		pos += 2;
5844bc52338SCy Schubert 		os_memcpy(pos, context, context_len);
5854bc52338SCy Schubert 	}
5864bc52338SCy Schubert 
5874bc52338SCy Schubert 	res = tls_prf(conn->rl.tls_version,
588f05cddf9SRui Paulo 		      conn->master_secret, TLS_MASTER_SECRET_LEN,
5894bc52338SCy Schubert 		      label, seed, seed_len, out, out_len);
5904bc52338SCy Schubert 	os_free(seed);
5914bc52338SCy Schubert 	return res;
59239beb93cSSam Leffler }
59339beb93cSSam Leffler 
59439beb93cSSam Leffler 
59539beb93cSSam Leffler /**
59639beb93cSSam Leffler  * tlsv1_client_get_cipher - Get current cipher name
59739beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
59839beb93cSSam Leffler  * @buf: Buffer for the cipher name
59939beb93cSSam Leffler  * @buflen: buf size
60039beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
60139beb93cSSam Leffler  *
60239beb93cSSam Leffler  * Get the name of the currently used cipher.
60339beb93cSSam Leffler  */
tlsv1_client_get_cipher(struct tlsv1_client * conn,char * buf,size_t buflen)60439beb93cSSam Leffler int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf,
60539beb93cSSam Leffler 			    size_t buflen)
60639beb93cSSam Leffler {
60739beb93cSSam Leffler 	char *cipher;
60839beb93cSSam Leffler 
60939beb93cSSam Leffler 	switch (conn->rl.cipher_suite) {
61039beb93cSSam Leffler 	case TLS_RSA_WITH_RC4_128_MD5:
61139beb93cSSam Leffler 		cipher = "RC4-MD5";
61239beb93cSSam Leffler 		break;
61339beb93cSSam Leffler 	case TLS_RSA_WITH_RC4_128_SHA:
61439beb93cSSam Leffler 		cipher = "RC4-SHA";
61539beb93cSSam Leffler 		break;
61639beb93cSSam Leffler 	case TLS_RSA_WITH_DES_CBC_SHA:
61739beb93cSSam Leffler 		cipher = "DES-CBC-SHA";
61839beb93cSSam Leffler 		break;
61939beb93cSSam Leffler 	case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
62039beb93cSSam Leffler 		cipher = "DES-CBC3-SHA";
62139beb93cSSam Leffler 		break;
6225b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_DES_CBC_SHA:
6235b9c547cSRui Paulo 		cipher = "DHE-RSA-DES-CBC-SHA";
6245b9c547cSRui Paulo 		break;
6255b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
6265b9c547cSRui Paulo 		cipher = "DHE-RSA-DES-CBC3-SHA";
6275b9c547cSRui Paulo 		break;
6285b9c547cSRui Paulo 	case TLS_DH_anon_WITH_RC4_128_MD5:
6295b9c547cSRui Paulo 		cipher = "ADH-RC4-MD5";
6305b9c547cSRui Paulo 		break;
6315b9c547cSRui Paulo 	case TLS_DH_anon_WITH_DES_CBC_SHA:
6325b9c547cSRui Paulo 		cipher = "ADH-DES-SHA";
6335b9c547cSRui Paulo 		break;
6345b9c547cSRui Paulo 	case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
6355b9c547cSRui Paulo 		cipher = "ADH-DES-CBC3-SHA";
6365b9c547cSRui Paulo 		break;
6375b9c547cSRui Paulo 	case TLS_RSA_WITH_AES_128_CBC_SHA:
6385b9c547cSRui Paulo 		cipher = "AES-128-SHA";
6395b9c547cSRui Paulo 		break;
6405b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
6415b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-128-SHA";
642f05cddf9SRui Paulo 		break;
64339beb93cSSam Leffler 	case TLS_DH_anon_WITH_AES_128_CBC_SHA:
64439beb93cSSam Leffler 		cipher = "ADH-AES-128-SHA";
64539beb93cSSam Leffler 		break;
64639beb93cSSam Leffler 	case TLS_RSA_WITH_AES_256_CBC_SHA:
64739beb93cSSam Leffler 		cipher = "AES-256-SHA";
64839beb93cSSam Leffler 		break;
6495b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
6505b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-256-SHA";
651f05cddf9SRui Paulo 		break;
6525b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_256_CBC_SHA:
6535b9c547cSRui Paulo 		cipher = "ADH-AES-256-SHA";
65439beb93cSSam Leffler 		break;
655f05cddf9SRui Paulo 	case TLS_RSA_WITH_AES_128_CBC_SHA256:
656f05cddf9SRui Paulo 		cipher = "AES-128-SHA256";
657f05cddf9SRui Paulo 		break;
6585b9c547cSRui Paulo 	case TLS_RSA_WITH_AES_256_CBC_SHA256:
6595b9c547cSRui Paulo 		cipher = "AES-256-SHA256";
6605b9c547cSRui Paulo 		break;
6615b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
6625b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-128-SHA256";
6635b9c547cSRui Paulo 		break;
6645b9c547cSRui Paulo 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
6655b9c547cSRui Paulo 		cipher = "DHE-RSA-AES-256-SHA256";
6665b9c547cSRui Paulo 		break;
6675b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
6685b9c547cSRui Paulo 		cipher = "ADH-AES-128-SHA256";
6695b9c547cSRui Paulo 		break;
6705b9c547cSRui Paulo 	case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
6715b9c547cSRui Paulo 		cipher = "ADH-AES-256-SHA256";
6725b9c547cSRui Paulo 		break;
67339beb93cSSam Leffler 	default:
67439beb93cSSam Leffler 		return -1;
67539beb93cSSam Leffler 	}
67639beb93cSSam Leffler 
67739beb93cSSam Leffler 	if (os_strlcpy(buf, cipher, buflen) >= buflen)
67839beb93cSSam Leffler 		return -1;
67939beb93cSSam Leffler 	return 0;
68039beb93cSSam Leffler }
68139beb93cSSam Leffler 
68239beb93cSSam Leffler 
68339beb93cSSam Leffler /**
68439beb93cSSam Leffler  * tlsv1_client_shutdown - Shutdown TLS connection
68539beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
68639beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
68739beb93cSSam Leffler  */
tlsv1_client_shutdown(struct tlsv1_client * conn)68839beb93cSSam Leffler int tlsv1_client_shutdown(struct tlsv1_client *conn)
68939beb93cSSam Leffler {
69039beb93cSSam Leffler 	conn->state = CLIENT_HELLO;
69139beb93cSSam Leffler 
69239beb93cSSam Leffler 	if (tls_verify_hash_init(&conn->verify) < 0) {
69339beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
69439beb93cSSam Leffler 			   "hash");
69539beb93cSSam Leffler 		return -1;
69639beb93cSSam Leffler 	}
69739beb93cSSam Leffler 
69839beb93cSSam Leffler 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
69939beb93cSSam Leffler 	tlsv1_record_change_write_cipher(&conn->rl);
70039beb93cSSam Leffler 	tlsv1_record_change_read_cipher(&conn->rl);
70139beb93cSSam Leffler 
70239beb93cSSam Leffler 	conn->certificate_requested = 0;
70339beb93cSSam Leffler 	crypto_public_key_free(conn->server_rsa_key);
70439beb93cSSam Leffler 	conn->server_rsa_key = NULL;
70539beb93cSSam Leffler 	conn->session_resumed = 0;
70639beb93cSSam Leffler 
70739beb93cSSam Leffler 	return 0;
70839beb93cSSam Leffler }
70939beb93cSSam Leffler 
71039beb93cSSam Leffler 
71139beb93cSSam Leffler /**
71239beb93cSSam Leffler  * tlsv1_client_resumed - Was session resumption used
71339beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
71439beb93cSSam Leffler  * Returns: 1 if current session used session resumption, 0 if not
71539beb93cSSam Leffler  */
tlsv1_client_resumed(struct tlsv1_client * conn)71639beb93cSSam Leffler int tlsv1_client_resumed(struct tlsv1_client *conn)
71739beb93cSSam Leffler {
71839beb93cSSam Leffler 	return !!conn->session_resumed;
71939beb93cSSam Leffler }
72039beb93cSSam Leffler 
72139beb93cSSam Leffler 
72239beb93cSSam Leffler /**
72339beb93cSSam Leffler  * tlsv1_client_hello_ext - Set TLS extension for ClientHello
72439beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
72539beb93cSSam Leffler  * @ext_type: Extension type
72639beb93cSSam Leffler  * @data: Extension payload (%NULL to remove extension)
72739beb93cSSam Leffler  * @data_len: Extension payload length
72839beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
72939beb93cSSam Leffler  */
tlsv1_client_hello_ext(struct tlsv1_client * conn,int ext_type,const u8 * data,size_t data_len)73039beb93cSSam Leffler int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
73139beb93cSSam Leffler 			   const u8 *data, size_t data_len)
73239beb93cSSam Leffler {
73339beb93cSSam Leffler 	u8 *pos;
73439beb93cSSam Leffler 
73539beb93cSSam Leffler 	conn->session_ticket_included = 0;
73639beb93cSSam Leffler 	os_free(conn->client_hello_ext);
73739beb93cSSam Leffler 	conn->client_hello_ext = NULL;
73839beb93cSSam Leffler 	conn->client_hello_ext_len = 0;
73939beb93cSSam Leffler 
74039beb93cSSam Leffler 	if (data == NULL || data_len == 0)
74139beb93cSSam Leffler 		return 0;
74239beb93cSSam Leffler 
743780fb4a2SCy Schubert 	pos = conn->client_hello_ext = os_malloc(4 + data_len);
74439beb93cSSam Leffler 	if (pos == NULL)
74539beb93cSSam Leffler 		return -1;
74639beb93cSSam Leffler 
74739beb93cSSam Leffler 	WPA_PUT_BE16(pos, ext_type);
74839beb93cSSam Leffler 	pos += 2;
74939beb93cSSam Leffler 	WPA_PUT_BE16(pos, data_len);
75039beb93cSSam Leffler 	pos += 2;
75139beb93cSSam Leffler 	os_memcpy(pos, data, data_len);
752780fb4a2SCy Schubert 	conn->client_hello_ext_len = 4 + data_len;
75339beb93cSSam Leffler 
75439beb93cSSam Leffler 	if (ext_type == TLS_EXT_PAC_OPAQUE) {
75539beb93cSSam Leffler 		conn->session_ticket_included = 1;
75639beb93cSSam Leffler 		wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket");
75739beb93cSSam Leffler 	}
75839beb93cSSam Leffler 
75939beb93cSSam Leffler 	return 0;
76039beb93cSSam Leffler }
76139beb93cSSam Leffler 
76239beb93cSSam Leffler 
76339beb93cSSam Leffler /**
764325151a3SRui Paulo  * tlsv1_client_get_random - Get random data from TLS connection
76539beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
766325151a3SRui Paulo  * @keys: Structure of random data (filled on success)
76739beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
76839beb93cSSam Leffler  */
tlsv1_client_get_random(struct tlsv1_client * conn,struct tls_random * keys)769325151a3SRui Paulo int tlsv1_client_get_random(struct tlsv1_client *conn, struct tls_random *keys)
77039beb93cSSam Leffler {
77139beb93cSSam Leffler 	os_memset(keys, 0, sizeof(*keys));
77239beb93cSSam Leffler 	if (conn->state == CLIENT_HELLO)
77339beb93cSSam Leffler 		return -1;
77439beb93cSSam Leffler 
77539beb93cSSam Leffler 	keys->client_random = conn->client_random;
77639beb93cSSam Leffler 	keys->client_random_len = TLS_RANDOM_LEN;
77739beb93cSSam Leffler 
77839beb93cSSam Leffler 	if (conn->state != SERVER_HELLO) {
77939beb93cSSam Leffler 		keys->server_random = conn->server_random;
78039beb93cSSam Leffler 		keys->server_random_len = TLS_RANDOM_LEN;
78139beb93cSSam Leffler 	}
78239beb93cSSam Leffler 
78339beb93cSSam Leffler 	return 0;
78439beb93cSSam Leffler }
78539beb93cSSam Leffler 
78639beb93cSSam Leffler 
78739beb93cSSam Leffler /**
78839beb93cSSam Leffler  * tlsv1_client_get_keyblock_size - Get TLS key_block size
78939beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
79039beb93cSSam Leffler  * Returns: Size of the key_block for the negotiated cipher suite or -1 on
79139beb93cSSam Leffler  * failure
79239beb93cSSam Leffler  */
tlsv1_client_get_keyblock_size(struct tlsv1_client * conn)79339beb93cSSam Leffler int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn)
79439beb93cSSam Leffler {
79539beb93cSSam Leffler 	if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
79639beb93cSSam Leffler 		return -1;
79739beb93cSSam Leffler 
79839beb93cSSam Leffler 	return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
79939beb93cSSam Leffler 		    conn->rl.iv_size);
80039beb93cSSam Leffler }
80139beb93cSSam Leffler 
80239beb93cSSam Leffler 
80339beb93cSSam Leffler /**
80439beb93cSSam Leffler  * tlsv1_client_set_cipher_list - Configure acceptable cipher suites
80539beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
80639beb93cSSam Leffler  * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
80739beb93cSSam Leffler  * (TLS_CIPHER_*).
80839beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
80939beb93cSSam Leffler  */
tlsv1_client_set_cipher_list(struct tlsv1_client * conn,u8 * ciphers)81039beb93cSSam Leffler int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
81139beb93cSSam Leffler {
81239beb93cSSam Leffler 	size_t count;
81339beb93cSSam Leffler 	u16 *suites;
81439beb93cSSam Leffler 
81539beb93cSSam Leffler 	/* TODO: implement proper configuration of cipher suites */
81639beb93cSSam Leffler 	if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
81739beb93cSSam Leffler 		count = 0;
81839beb93cSSam Leffler 		suites = conn->cipher_suites;
819f05cddf9SRui Paulo 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256;
82039beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
821f05cddf9SRui Paulo 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256;
82239beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
82339beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
82439beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
82539beb93cSSam Leffler 		suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
8263157ba21SRui Paulo 
8273157ba21SRui Paulo 		/*
8283157ba21SRui Paulo 		 * Cisco AP (at least 350 and 1200 series) local authentication
8293157ba21SRui Paulo 		 * server does not know how to search cipher suites from the
8303157ba21SRui Paulo 		 * list and seem to require that the last entry in the list is
8313157ba21SRui Paulo 		 * the one that it wants to use. However, TLS specification
8323157ba21SRui Paulo 		 * requires the list to be in the client preference order. As a
8333157ba21SRui Paulo 		 * workaround, add anon-DH AES-128-SHA1 again at the end of the
8343157ba21SRui Paulo 		 * list to allow the Cisco code to find it.
8353157ba21SRui Paulo 		 */
8363157ba21SRui Paulo 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
83739beb93cSSam Leffler 		conn->num_cipher_suites = count;
83839beb93cSSam Leffler 	}
83939beb93cSSam Leffler 
84039beb93cSSam Leffler 	return 0;
84139beb93cSSam Leffler }
84239beb93cSSam Leffler 
84339beb93cSSam Leffler 
84439beb93cSSam Leffler /**
84539beb93cSSam Leffler  * tlsv1_client_set_cred - Set client credentials
84639beb93cSSam Leffler  * @conn: TLSv1 client connection data from tlsv1_client_init()
84739beb93cSSam Leffler  * @cred: Credentials from tlsv1_cred_alloc()
84839beb93cSSam Leffler  * Returns: 0 on success, -1 on failure
84939beb93cSSam Leffler  *
85039beb93cSSam Leffler  * On success, the client takes ownership of the credentials block and caller
85139beb93cSSam Leffler  * must not free it. On failure, caller is responsible for freeing the
85239beb93cSSam Leffler  * credential block.
85339beb93cSSam Leffler  */
tlsv1_client_set_cred(struct tlsv1_client * conn,struct tlsv1_credentials * cred)85439beb93cSSam Leffler int tlsv1_client_set_cred(struct tlsv1_client *conn,
85539beb93cSSam Leffler 			  struct tlsv1_credentials *cred)
85639beb93cSSam Leffler {
85739beb93cSSam Leffler 	tlsv1_cred_free(conn->cred);
85839beb93cSSam Leffler 	conn->cred = cred;
85939beb93cSSam Leffler 	return 0;
86039beb93cSSam Leffler }
86139beb93cSSam Leffler 
86239beb93cSSam Leffler 
863780fb4a2SCy Schubert /**
864780fb4a2SCy Schubert  * tlsv1_client_set_flags - Set connection flags
865780fb4a2SCy Schubert  * @conn: TLSv1 client connection data from tlsv1_client_init()
866780fb4a2SCy Schubert  * @flags: TLS_CONN_* bitfield
867780fb4a2SCy Schubert  */
tlsv1_client_set_flags(struct tlsv1_client * conn,unsigned int flags)868780fb4a2SCy Schubert void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
869f05cddf9SRui Paulo {
870780fb4a2SCy Schubert 	conn->flags = flags;
871*c1d255d3SCy Schubert 	conn->rl.tls_version = tls_client_highest_ver(conn);
872f05cddf9SRui Paulo }
873f05cddf9SRui Paulo 
874f05cddf9SRui Paulo 
tlsv1_client_set_session_ticket_cb(struct tlsv1_client * conn,tlsv1_client_session_ticket_cb cb,void * ctx)87539beb93cSSam Leffler void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
87639beb93cSSam Leffler 					tlsv1_client_session_ticket_cb cb,
87739beb93cSSam Leffler 					void *ctx)
87839beb93cSSam Leffler {
87939beb93cSSam Leffler 	wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
88039beb93cSSam Leffler 		   cb, ctx);
88139beb93cSSam Leffler 	conn->session_ticket_cb = cb;
88239beb93cSSam Leffler 	conn->session_ticket_cb_ctx = ctx;
88339beb93cSSam Leffler }
884780fb4a2SCy Schubert 
885780fb4a2SCy Schubert 
tlsv1_client_set_cb(struct tlsv1_client * conn,void (* event_cb)(void * ctx,enum tls_event ev,union tls_event_data * data),void * cb_ctx,int cert_in_cb)886780fb4a2SCy Schubert void tlsv1_client_set_cb(struct tlsv1_client *conn,
887780fb4a2SCy Schubert 			 void (*event_cb)(void *ctx, enum tls_event ev,
888780fb4a2SCy Schubert 					  union tls_event_data *data),
889780fb4a2SCy Schubert 			 void *cb_ctx,
890780fb4a2SCy Schubert 			 int cert_in_cb)
891780fb4a2SCy Schubert {
892780fb4a2SCy Schubert 	conn->event_cb = event_cb;
893780fb4a2SCy Schubert 	conn->cb_ctx = cb_ctx;
894780fb4a2SCy Schubert 	conn->cert_in_cb = !!cert_in_cb;
895780fb4a2SCy Schubert }
896780fb4a2SCy Schubert 
897780fb4a2SCy Schubert 
tlsv1_client_get_version(struct tlsv1_client * conn,char * buf,size_t buflen)898780fb4a2SCy Schubert int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
899780fb4a2SCy Schubert 			     size_t buflen)
900780fb4a2SCy Schubert {
901780fb4a2SCy Schubert 	if (!conn)
902780fb4a2SCy Schubert 		return -1;
903780fb4a2SCy Schubert 	switch (conn->rl.tls_version) {
904780fb4a2SCy Schubert 	case TLS_VERSION_1:
905780fb4a2SCy Schubert 		os_strlcpy(buf, "TLSv1", buflen);
906780fb4a2SCy Schubert 		break;
907780fb4a2SCy Schubert 	case TLS_VERSION_1_1:
908780fb4a2SCy Schubert 		os_strlcpy(buf, "TLSv1.1", buflen);
909780fb4a2SCy Schubert 		break;
910780fb4a2SCy Schubert 	case TLS_VERSION_1_2:
911780fb4a2SCy Schubert 		os_strlcpy(buf, "TLSv1.2", buflen);
912780fb4a2SCy Schubert 		break;
913780fb4a2SCy Schubert 	default:
914780fb4a2SCy Schubert 		return -1;
915780fb4a2SCy Schubert 	}
916780fb4a2SCy Schubert 
917780fb4a2SCy Schubert 	return 0;
918780fb4a2SCy Schubert }
919