xref: /netbsd/external/bsd/wpa/dist/src/tls/tlsv1_client.c (revision 0d69f216)
18dbcf02cSchristos /*
262a52023Schristos  * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
3*0d69f216Schristos  * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
562a52023Schristos  * This software may be distributed under the terms of the BSD license.
662a52023Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos 
118dbcf02cSchristos #include "common.h"
128dbcf02cSchristos #include "crypto/sha1.h"
138dbcf02cSchristos #include "crypto/tls.h"
14928750b6Schristos #include "x509v3.h"
158dbcf02cSchristos #include "tlsv1_common.h"
168dbcf02cSchristos #include "tlsv1_record.h"
178dbcf02cSchristos #include "tlsv1_client.h"
188dbcf02cSchristos #include "tlsv1_client_i.h"
198dbcf02cSchristos 
208dbcf02cSchristos /* TODO:
218dbcf02cSchristos  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
228dbcf02cSchristos  */
238dbcf02cSchristos 
248dbcf02cSchristos 
tls_alert(struct tlsv1_client * conn,u8 level,u8 description)258dbcf02cSchristos void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
268dbcf02cSchristos {
278dbcf02cSchristos 	conn->alert_level = level;
288dbcf02cSchristos 	conn->alert_description = description;
298dbcf02cSchristos }
308dbcf02cSchristos 
318dbcf02cSchristos 
tlsv1_client_free_dh(struct tlsv1_client * conn)328dbcf02cSchristos void tlsv1_client_free_dh(struct tlsv1_client *conn)
338dbcf02cSchristos {
348dbcf02cSchristos 	os_free(conn->dh_p);
358dbcf02cSchristos 	os_free(conn->dh_g);
368dbcf02cSchristos 	os_free(conn->dh_ys);
378dbcf02cSchristos 	conn->dh_p = conn->dh_g = conn->dh_ys = NULL;
388dbcf02cSchristos }
398dbcf02cSchristos 
408dbcf02cSchristos 
tls_derive_pre_master_secret(u8 * pre_master_secret)418dbcf02cSchristos int tls_derive_pre_master_secret(u8 *pre_master_secret)
428dbcf02cSchristos {
438dbcf02cSchristos 	WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
448dbcf02cSchristos 	if (os_get_random(pre_master_secret + 2,
458dbcf02cSchristos 			  TLS_PRE_MASTER_SECRET_LEN - 2))
468dbcf02cSchristos 		return -1;
478dbcf02cSchristos 	return 0;
488dbcf02cSchristos }
498dbcf02cSchristos 
508dbcf02cSchristos 
tls_derive_keys(struct tlsv1_client * conn,const u8 * pre_master_secret,size_t pre_master_secret_len)518dbcf02cSchristos int tls_derive_keys(struct tlsv1_client *conn,
528dbcf02cSchristos 		    const u8 *pre_master_secret, size_t pre_master_secret_len)
538dbcf02cSchristos {
548dbcf02cSchristos 	u8 seed[2 * TLS_RANDOM_LEN];
558dbcf02cSchristos 	u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
568dbcf02cSchristos 	u8 *pos;
578dbcf02cSchristos 	size_t key_block_len;
588dbcf02cSchristos 
598dbcf02cSchristos 	if (pre_master_secret) {
608dbcf02cSchristos 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
618dbcf02cSchristos 				pre_master_secret, pre_master_secret_len);
628dbcf02cSchristos 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
638dbcf02cSchristos 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
648dbcf02cSchristos 			  TLS_RANDOM_LEN);
6562a52023Schristos 		if (tls_prf(conn->rl.tls_version,
6662a52023Schristos 			    pre_master_secret, pre_master_secret_len,
678dbcf02cSchristos 			    "master secret", seed, 2 * TLS_RANDOM_LEN,
688dbcf02cSchristos 			    conn->master_secret, TLS_MASTER_SECRET_LEN)) {
698dbcf02cSchristos 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
708dbcf02cSchristos 				   "master_secret");
718dbcf02cSchristos 			return -1;
728dbcf02cSchristos 		}
738dbcf02cSchristos 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
748dbcf02cSchristos 				conn->master_secret, TLS_MASTER_SECRET_LEN);
758dbcf02cSchristos 	}
768dbcf02cSchristos 
778dbcf02cSchristos 	os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
788dbcf02cSchristos 	os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
7942669be3Schristos 	key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len);
8042669be3Schristos 	if (conn->rl.tls_version == TLS_VERSION_1)
8142669be3Schristos 		key_block_len += 2 * conn->rl.iv_size;
8262a52023Schristos 	if (tls_prf(conn->rl.tls_version,
8362a52023Schristos 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
848dbcf02cSchristos 		    "key expansion", seed, 2 * TLS_RANDOM_LEN,
858dbcf02cSchristos 		    key_block, key_block_len)) {
868dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
878dbcf02cSchristos 		return -1;
888dbcf02cSchristos 	}
898dbcf02cSchristos 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
908dbcf02cSchristos 			key_block, key_block_len);
918dbcf02cSchristos 
928dbcf02cSchristos 	pos = key_block;
938dbcf02cSchristos 
948dbcf02cSchristos 	/* client_write_MAC_secret */
958dbcf02cSchristos 	os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
968dbcf02cSchristos 	pos += conn->rl.hash_size;
978dbcf02cSchristos 	/* server_write_MAC_secret */
988dbcf02cSchristos 	os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
998dbcf02cSchristos 	pos += conn->rl.hash_size;
1008dbcf02cSchristos 
1018dbcf02cSchristos 	/* client_write_key */
1028dbcf02cSchristos 	os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
1038dbcf02cSchristos 	pos += conn->rl.key_material_len;
1048dbcf02cSchristos 	/* server_write_key */
1058dbcf02cSchristos 	os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
1068dbcf02cSchristos 	pos += conn->rl.key_material_len;
1078dbcf02cSchristos 
10842669be3Schristos 	if (conn->rl.tls_version == TLS_VERSION_1) {
1098dbcf02cSchristos 		/* client_write_IV */
1108dbcf02cSchristos 		os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
1118dbcf02cSchristos 		pos += conn->rl.iv_size;
1128dbcf02cSchristos 		/* server_write_IV */
1138dbcf02cSchristos 		os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
11442669be3Schristos 	} else {
11542669be3Schristos 		/*
11642669be3Schristos 		 * Use IV field to set the mask value for TLS v1.1. A fixed
11742669be3Schristos 		 * mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block
11842669be3Schristos 		 * Cipher option 2a.
11942669be3Schristos 		 */
12042669be3Schristos 		os_memset(conn->rl.write_iv, 0, conn->rl.iv_size);
12142669be3Schristos 	}
1228dbcf02cSchristos 
1238dbcf02cSchristos 	return 0;
1248dbcf02cSchristos }
1258dbcf02cSchristos 
1268dbcf02cSchristos 
1278dbcf02cSchristos /**
1288dbcf02cSchristos  * tlsv1_client_handshake - Process TLS handshake
1298dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
1308dbcf02cSchristos  * @in_data: Input data from TLS peer
1318dbcf02cSchristos  * @in_len: Input data length
1328dbcf02cSchristos  * @out_len: Length of the output buffer.
1338dbcf02cSchristos  * @appl_data: Pointer to application data pointer, or %NULL if dropped
1348dbcf02cSchristos  * @appl_data_len: Pointer to variable that is set to appl_data length
13562a52023Schristos  * @need_more_data: Set to 1 if more data would be needed to complete
13662a52023Schristos  *	processing
1378dbcf02cSchristos  * Returns: Pointer to output data, %NULL on failure
1388dbcf02cSchristos  */
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)1398dbcf02cSchristos u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
1408dbcf02cSchristos 			    const u8 *in_data, size_t in_len,
1418dbcf02cSchristos 			    size_t *out_len, u8 **appl_data,
14262a52023Schristos 			    size_t *appl_data_len, int *need_more_data)
1438dbcf02cSchristos {
1448dbcf02cSchristos 	const u8 *pos, *end;
14562a52023Schristos 	u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct;
1468dbcf02cSchristos 	size_t in_msg_len;
1478dbcf02cSchristos 	int no_appl_data;
14862a52023Schristos 	int used;
14962a52023Schristos 
15062a52023Schristos 	if (need_more_data)
15162a52023Schristos 		*need_more_data = 0;
1528dbcf02cSchristos 
1538dbcf02cSchristos 	if (conn->state == CLIENT_HELLO) {
1548dbcf02cSchristos 		if (in_len)
1558dbcf02cSchristos 			return NULL;
1568dbcf02cSchristos 		return tls_send_client_hello(conn, out_len);
1578dbcf02cSchristos 	}
1588dbcf02cSchristos 
15962a52023Schristos 	if (conn->partial_input) {
16062a52023Schristos 		if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
16162a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
16262a52023Schristos 				   "memory for pending record");
16362a52023Schristos 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
16462a52023Schristos 				  TLS_ALERT_INTERNAL_ERROR);
16562a52023Schristos 			goto failed;
16662a52023Schristos 		}
16762a52023Schristos 		wpabuf_put_data(conn->partial_input, in_data, in_len);
16862a52023Schristos 		in_data = wpabuf_head(conn->partial_input);
16962a52023Schristos 		in_len = wpabuf_len(conn->partial_input);
17062a52023Schristos 	}
17162a52023Schristos 
1728dbcf02cSchristos 	if (in_data == NULL || in_len == 0)
1738dbcf02cSchristos 		return NULL;
1748dbcf02cSchristos 
1758dbcf02cSchristos 	pos = in_data;
1768dbcf02cSchristos 	end = in_data + in_len;
1778dbcf02cSchristos 	in_msg = os_malloc(in_len);
1788dbcf02cSchristos 	if (in_msg == NULL)
1798dbcf02cSchristos 		return NULL;
1808dbcf02cSchristos 
1818dbcf02cSchristos 	/* Each received packet may include multiple records */
1828dbcf02cSchristos 	while (pos < end) {
1838dbcf02cSchristos 		in_msg_len = in_len;
18462a52023Schristos 		used = tlsv1_record_receive(&conn->rl, pos, end - pos,
18562a52023Schristos 					    in_msg, &in_msg_len, &alert);
18662a52023Schristos 		if (used < 0) {
1878dbcf02cSchristos 			wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
1888dbcf02cSchristos 				   "record failed");
1898dbcf02cSchristos 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
1908dbcf02cSchristos 			goto failed;
1918dbcf02cSchristos 		}
19262a52023Schristos 		if (used == 0) {
19362a52023Schristos 			struct wpabuf *partial;
19462a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
19562a52023Schristos 			partial = wpabuf_alloc_copy(pos, end - pos);
19662a52023Schristos 			wpabuf_free(conn->partial_input);
19762a52023Schristos 			conn->partial_input = partial;
19862a52023Schristos 			if (conn->partial_input == NULL) {
19962a52023Schristos 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
20062a52023Schristos 					   "allocate memory for pending "
20162a52023Schristos 					   "record");
20262a52023Schristos 				tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
20362a52023Schristos 					  TLS_ALERT_INTERNAL_ERROR);
20462a52023Schristos 				goto failed;
20562a52023Schristos 			}
20662a52023Schristos 			os_free(in_msg);
20762a52023Schristos 			if (need_more_data)
20862a52023Schristos 				*need_more_data = 1;
20962a52023Schristos 			return NULL;
21062a52023Schristos 		}
2118dbcf02cSchristos 		ct = pos[0];
2128dbcf02cSchristos 
2138dbcf02cSchristos 		in_pos = in_msg;
2148dbcf02cSchristos 		in_end = in_msg + in_msg_len;
2158dbcf02cSchristos 
2168dbcf02cSchristos 		/* Each received record may include multiple messages of the
2178dbcf02cSchristos 		 * same ContentType. */
2188dbcf02cSchristos 		while (in_pos < in_end) {
2198dbcf02cSchristos 			in_msg_len = in_end - in_pos;
2208dbcf02cSchristos 			if (tlsv1_client_process_handshake(conn, ct, in_pos,
2218dbcf02cSchristos 							   &in_msg_len,
2228dbcf02cSchristos 							   appl_data,
2238dbcf02cSchristos 							   appl_data_len) < 0)
2248dbcf02cSchristos 				goto failed;
2258dbcf02cSchristos 			in_pos += in_msg_len;
2268dbcf02cSchristos 		}
2278dbcf02cSchristos 
22862a52023Schristos 		pos += used;
2298dbcf02cSchristos 	}
2308dbcf02cSchristos 
2318dbcf02cSchristos 	os_free(in_msg);
2328dbcf02cSchristos 	in_msg = NULL;
2338dbcf02cSchristos 
2348dbcf02cSchristos 	no_appl_data = appl_data == NULL || *appl_data == NULL;
2358dbcf02cSchristos 	msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data);
2368dbcf02cSchristos 
2378dbcf02cSchristos failed:
2388dbcf02cSchristos 	os_free(in_msg);
2398dbcf02cSchristos 	if (conn->alert_level) {
24062a52023Schristos 		wpabuf_free(conn->partial_input);
24162a52023Schristos 		conn->partial_input = NULL;
2428dbcf02cSchristos 		conn->state = FAILED;
2438dbcf02cSchristos 		os_free(msg);
2448dbcf02cSchristos 		msg = tlsv1_client_send_alert(conn, conn->alert_level,
2458dbcf02cSchristos 					      conn->alert_description,
2468dbcf02cSchristos 					      out_len);
2478dbcf02cSchristos 	} else if (msg == NULL) {
2488dbcf02cSchristos 		msg = os_zalloc(1);
2498dbcf02cSchristos 		*out_len = 0;
2508dbcf02cSchristos 	}
2518dbcf02cSchristos 
25262a52023Schristos 	if (need_more_data == NULL || !(*need_more_data)) {
25362a52023Schristos 		wpabuf_free(conn->partial_input);
25462a52023Schristos 		conn->partial_input = NULL;
25562a52023Schristos 	}
25662a52023Schristos 
2578dbcf02cSchristos 	return msg;
2588dbcf02cSchristos }
2598dbcf02cSchristos 
2608dbcf02cSchristos 
2618dbcf02cSchristos /**
2628dbcf02cSchristos  * tlsv1_client_encrypt - Encrypt data into TLS tunnel
2638dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
2648dbcf02cSchristos  * @in_data: Pointer to plaintext data to be encrypted
2658dbcf02cSchristos  * @in_len: Input buffer length
2668dbcf02cSchristos  * @out_data: Pointer to output buffer (encrypted TLS data)
2678dbcf02cSchristos  * @out_len: Maximum out_data length
2688dbcf02cSchristos  * Returns: Number of bytes written to out_data, -1 on failure
2698dbcf02cSchristos  *
2708dbcf02cSchristos  * This function is used after TLS handshake has been completed successfully to
2718dbcf02cSchristos  * send data in the encrypted tunnel.
2728dbcf02cSchristos  */
tlsv1_client_encrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)2738dbcf02cSchristos int tlsv1_client_encrypt(struct tlsv1_client *conn,
2748dbcf02cSchristos 			 const u8 *in_data, size_t in_len,
2758dbcf02cSchristos 			 u8 *out_data, size_t out_len)
2768dbcf02cSchristos {
2778dbcf02cSchristos 	size_t rlen;
2788dbcf02cSchristos 
2798dbcf02cSchristos 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
2808dbcf02cSchristos 			in_data, in_len);
2818dbcf02cSchristos 
2828dbcf02cSchristos 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
28342669be3Schristos 			      out_data, out_len, in_data, in_len, &rlen) < 0) {
2848dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
2858dbcf02cSchristos 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2868dbcf02cSchristos 			  TLS_ALERT_INTERNAL_ERROR);
2878dbcf02cSchristos 		return -1;
2888dbcf02cSchristos 	}
2898dbcf02cSchristos 
2908dbcf02cSchristos 	return rlen;
2918dbcf02cSchristos }
2928dbcf02cSchristos 
2938dbcf02cSchristos 
2948dbcf02cSchristos /**
2958dbcf02cSchristos  * tlsv1_client_decrypt - Decrypt data from TLS tunnel
2968dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
2978dbcf02cSchristos  * @in_data: Pointer to input buffer (encrypted TLS data)
2988dbcf02cSchristos  * @in_len: Input buffer length
29962a52023Schristos  * @need_more_data: Set to 1 if more data would be needed to complete
30062a52023Schristos  *	processing
30162a52023Schristos  * Returns: Decrypted data or %NULL on failure
3028dbcf02cSchristos  *
3038dbcf02cSchristos  * This function is used after TLS handshake has been completed successfully to
3048dbcf02cSchristos  * receive data from the encrypted tunnel.
3058dbcf02cSchristos  */
tlsv1_client_decrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,int * need_more_data)30662a52023Schristos struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn,
3078dbcf02cSchristos 				     const u8 *in_data, size_t in_len,
30862a52023Schristos 				     int *need_more_data)
3098dbcf02cSchristos {
3108dbcf02cSchristos 	const u8 *in_end, *pos;
31162a52023Schristos 	int used;
31262a52023Schristos 	u8 alert, *out_pos, ct;
3138dbcf02cSchristos 	size_t olen;
31462a52023Schristos 	struct wpabuf *buf = NULL;
31562a52023Schristos 
31662a52023Schristos 	if (need_more_data)
31762a52023Schristos 		*need_more_data = 0;
31862a52023Schristos 
31962a52023Schristos 	if (conn->partial_input) {
32062a52023Schristos 		if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
32162a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
32262a52023Schristos 				   "memory for pending record");
32362a52023Schristos 			alert = TLS_ALERT_INTERNAL_ERROR;
32462a52023Schristos 			goto fail;
32562a52023Schristos 		}
32662a52023Schristos 		wpabuf_put_data(conn->partial_input, in_data, in_len);
32762a52023Schristos 		in_data = wpabuf_head(conn->partial_input);
32862a52023Schristos 		in_len = wpabuf_len(conn->partial_input);
32962a52023Schristos 	}
3308dbcf02cSchristos 
3318dbcf02cSchristos 	pos = in_data;
3328dbcf02cSchristos 	in_end = in_data + in_len;
3338dbcf02cSchristos 
3348dbcf02cSchristos 	while (pos < in_end) {
33562a52023Schristos 		ct = pos[0];
33662a52023Schristos 		if (wpabuf_resize(&buf, in_end - pos) < 0) {
33762a52023Schristos 			alert = TLS_ALERT_INTERNAL_ERROR;
33862a52023Schristos 			goto fail;
3398dbcf02cSchristos 		}
34062a52023Schristos 		out_pos = wpabuf_put(buf, 0);
34162a52023Schristos 		olen = wpabuf_tailroom(buf);
34262a52023Schristos 		used = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
3438dbcf02cSchristos 					    out_pos, &olen, &alert);
34462a52023Schristos 		if (used < 0) {
3458dbcf02cSchristos 			wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
3468dbcf02cSchristos 				   "failed");
34762a52023Schristos 			goto fail;
34862a52023Schristos 		}
34962a52023Schristos 		if (used == 0) {
35062a52023Schristos 			struct wpabuf *partial;
35162a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
35262a52023Schristos 			partial = wpabuf_alloc_copy(pos, in_end - pos);
35362a52023Schristos 			wpabuf_free(conn->partial_input);
35462a52023Schristos 			conn->partial_input = partial;
35562a52023Schristos 			if (conn->partial_input == NULL) {
35662a52023Schristos 				wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
35762a52023Schristos 					   "allocate memory for pending "
35862a52023Schristos 					   "record");
35962a52023Schristos 				alert = TLS_ALERT_INTERNAL_ERROR;
36062a52023Schristos 				goto fail;
36162a52023Schristos 			}
36262a52023Schristos 			if (need_more_data)
36362a52023Schristos 				*need_more_data = 1;
36462a52023Schristos 			return buf;
36562a52023Schristos 		}
36662a52023Schristos 
36762a52023Schristos 		if (ct == TLS_CONTENT_TYPE_ALERT) {
36862a52023Schristos 			if (olen < 2) {
36962a52023Schristos 				wpa_printf(MSG_DEBUG, "TLSv1: Alert "
37062a52023Schristos 					   "underflow");
37162a52023Schristos 				alert = TLS_ALERT_DECODE_ERROR;
37262a52023Schristos 				goto fail;
37362a52023Schristos 			}
37462a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
37562a52023Schristos 				   out_pos[0], out_pos[1]);
37662a52023Schristos 			if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) {
37762a52023Schristos 				/* Continue processing */
37862a52023Schristos 				pos += used;
37962a52023Schristos 				continue;
38062a52023Schristos 			}
38162a52023Schristos 
38262a52023Schristos 			alert = out_pos[1];
38362a52023Schristos 			goto fail;
38462a52023Schristos 		}
38562a52023Schristos 
38662a52023Schristos 		if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
38762a52023Schristos 			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
38862a52023Schristos 				   "0x%x when decrypting application data",
38962a52023Schristos 				   pos[0]);
39062a52023Schristos 			alert = TLS_ALERT_UNEXPECTED_MESSAGE;
39162a52023Schristos 			goto fail;
39262a52023Schristos 		}
39362a52023Schristos 
39462a52023Schristos 		wpabuf_put(buf, olen);
39562a52023Schristos 
39662a52023Schristos 		pos += used;
39762a52023Schristos 	}
39862a52023Schristos 
39962a52023Schristos 	wpabuf_free(conn->partial_input);
40062a52023Schristos 	conn->partial_input = NULL;
40162a52023Schristos 	return buf;
40262a52023Schristos 
40362a52023Schristos fail:
40462a52023Schristos 	wpabuf_free(buf);
40562a52023Schristos 	wpabuf_free(conn->partial_input);
40662a52023Schristos 	conn->partial_input = NULL;
4078dbcf02cSchristos 	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
40862a52023Schristos 	return NULL;
4098dbcf02cSchristos }
4108dbcf02cSchristos 
4118dbcf02cSchristos 
4128dbcf02cSchristos /**
4138dbcf02cSchristos  * tlsv1_client_global_init - Initialize TLSv1 client
4148dbcf02cSchristos  * Returns: 0 on success, -1 on failure
4158dbcf02cSchristos  *
4168dbcf02cSchristos  * This function must be called before using any other TLSv1 client functions.
4178dbcf02cSchristos  */
tlsv1_client_global_init(void)4188dbcf02cSchristos int tlsv1_client_global_init(void)
4198dbcf02cSchristos {
4208dbcf02cSchristos 	return crypto_global_init();
4218dbcf02cSchristos }
4228dbcf02cSchristos 
4238dbcf02cSchristos 
4248dbcf02cSchristos /**
4258dbcf02cSchristos  * tlsv1_client_global_deinit - Deinitialize TLSv1 client
4268dbcf02cSchristos  *
4278dbcf02cSchristos  * This function can be used to deinitialize the TLSv1 client that was
4288dbcf02cSchristos  * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions
4298dbcf02cSchristos  * can be called after this before calling tlsv1_client_global_init() again.
4308dbcf02cSchristos  */
tlsv1_client_global_deinit(void)4318dbcf02cSchristos void tlsv1_client_global_deinit(void)
4328dbcf02cSchristos {
4338dbcf02cSchristos 	crypto_global_deinit();
4348dbcf02cSchristos }
4358dbcf02cSchristos 
4368dbcf02cSchristos 
4378dbcf02cSchristos /**
4388dbcf02cSchristos  * tlsv1_client_init - Initialize TLSv1 client connection
4398dbcf02cSchristos  * Returns: Pointer to TLSv1 client connection data or %NULL on failure
4408dbcf02cSchristos  */
tlsv1_client_init(void)4418dbcf02cSchristos struct tlsv1_client * tlsv1_client_init(void)
4428dbcf02cSchristos {
4438dbcf02cSchristos 	struct tlsv1_client *conn;
4448dbcf02cSchristos 	size_t count;
4458dbcf02cSchristos 	u16 *suites;
4468dbcf02cSchristos 
4478dbcf02cSchristos 	conn = os_zalloc(sizeof(*conn));
4488dbcf02cSchristos 	if (conn == NULL)
4498dbcf02cSchristos 		return NULL;
4508dbcf02cSchristos 
4518dbcf02cSchristos 	conn->state = CLIENT_HELLO;
4528dbcf02cSchristos 
4538dbcf02cSchristos 	if (tls_verify_hash_init(&conn->verify) < 0) {
4548dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
4558dbcf02cSchristos 			   "hash");
4568dbcf02cSchristos 		os_free(conn);
4578dbcf02cSchristos 		return NULL;
4588dbcf02cSchristos 	}
4598dbcf02cSchristos 
4608dbcf02cSchristos 	count = 0;
4618dbcf02cSchristos 	suites = conn->cipher_suites;
46236d97821Schristos 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
46362a52023Schristos 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
46436d97821Schristos 	suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
4658dbcf02cSchristos 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
46636d97821Schristos 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
46762a52023Schristos 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
46836d97821Schristos 	suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
4698dbcf02cSchristos 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
47036d97821Schristos 	suites[count++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
4718dbcf02cSchristos 	suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
4728dbcf02cSchristos 	suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
4738dbcf02cSchristos 	suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
4748dbcf02cSchristos 	conn->num_cipher_suites = count;
4758dbcf02cSchristos 
47642669be3Schristos 	conn->rl.tls_version = TLS_VERSION;
47742669be3Schristos 
4788dbcf02cSchristos 	return conn;
4798dbcf02cSchristos }
4808dbcf02cSchristos 
4818dbcf02cSchristos 
4828dbcf02cSchristos /**
4838dbcf02cSchristos  * tlsv1_client_deinit - Deinitialize TLSv1 client connection
4848dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
4858dbcf02cSchristos  */
tlsv1_client_deinit(struct tlsv1_client * conn)4868dbcf02cSchristos void tlsv1_client_deinit(struct tlsv1_client *conn)
4878dbcf02cSchristos {
4888dbcf02cSchristos 	crypto_public_key_free(conn->server_rsa_key);
4898dbcf02cSchristos 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
4908dbcf02cSchristos 	tlsv1_record_change_write_cipher(&conn->rl);
4918dbcf02cSchristos 	tlsv1_record_change_read_cipher(&conn->rl);
4928dbcf02cSchristos 	tls_verify_hash_free(&conn->verify);
4938dbcf02cSchristos 	os_free(conn->client_hello_ext);
4948dbcf02cSchristos 	tlsv1_client_free_dh(conn);
4958dbcf02cSchristos 	tlsv1_cred_free(conn->cred);
49662a52023Schristos 	wpabuf_free(conn->partial_input);
497928750b6Schristos 	x509_certificate_chain_free(conn->server_cert);
4988dbcf02cSchristos 	os_free(conn);
4998dbcf02cSchristos }
5008dbcf02cSchristos 
5018dbcf02cSchristos 
5028dbcf02cSchristos /**
5038dbcf02cSchristos  * tlsv1_client_established - Check whether connection has been established
5048dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
5058dbcf02cSchristos  * Returns: 1 if connection is established, 0 if not
5068dbcf02cSchristos  */
tlsv1_client_established(struct tlsv1_client * conn)5078dbcf02cSchristos int tlsv1_client_established(struct tlsv1_client *conn)
5088dbcf02cSchristos {
5098dbcf02cSchristos 	return conn->state == ESTABLISHED;
5108dbcf02cSchristos }
5118dbcf02cSchristos 
5128dbcf02cSchristos 
5138dbcf02cSchristos /**
5148dbcf02cSchristos  * tlsv1_client_prf - Use TLS-PRF to derive keying material
5158dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
5168dbcf02cSchristos  * @label: Label (e.g., description of the key) for PRF
517*0d69f216Schristos  * @context: Optional extra upper-layer context (max len 2^16)
518*0d69f216Schristos  * @context_len: The length of the context value
5198dbcf02cSchristos  * @server_random_first: seed is 0 = client_random|server_random,
5208dbcf02cSchristos  * 1 = server_random|client_random
5218dbcf02cSchristos  * @out: Buffer for output data from TLS-PRF
5228dbcf02cSchristos  * @out_len: Length of the output buffer
5238dbcf02cSchristos  * Returns: 0 on success, -1 on failure
5248dbcf02cSchristos  */
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)5258dbcf02cSchristos int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
526*0d69f216Schristos 		     const u8 *context, size_t context_len,
5278dbcf02cSchristos 		     int server_random_first, u8 *out, size_t out_len)
5288dbcf02cSchristos {
529*0d69f216Schristos 	u8 *seed, *pos;
530*0d69f216Schristos 	size_t seed_len = 2 * TLS_RANDOM_LEN;
531*0d69f216Schristos 	int res;
5328dbcf02cSchristos 
5338dbcf02cSchristos 	if (conn->state != ESTABLISHED)
5348dbcf02cSchristos 		return -1;
5358dbcf02cSchristos 
536*0d69f216Schristos 	if (context_len > 65535)
537*0d69f216Schristos 		return -1;
538*0d69f216Schristos 
539*0d69f216Schristos 	if (context)
540*0d69f216Schristos 		seed_len += 2 + context_len;
541*0d69f216Schristos 
542*0d69f216Schristos 	seed = os_malloc(seed_len);
543*0d69f216Schristos 	if (!seed)
544*0d69f216Schristos 		return -1;
545*0d69f216Schristos 
5468dbcf02cSchristos 	if (server_random_first) {
5478dbcf02cSchristos 		os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
5488dbcf02cSchristos 		os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
5498dbcf02cSchristos 			  TLS_RANDOM_LEN);
5508dbcf02cSchristos 	} else {
5518dbcf02cSchristos 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
5528dbcf02cSchristos 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
5538dbcf02cSchristos 			  TLS_RANDOM_LEN);
5548dbcf02cSchristos 	}
5558dbcf02cSchristos 
556*0d69f216Schristos 	if (context) {
557*0d69f216Schristos 		pos = seed + 2 * TLS_RANDOM_LEN;
558*0d69f216Schristos 		WPA_PUT_BE16(pos, context_len);
559*0d69f216Schristos 		pos += 2;
560*0d69f216Schristos 		os_memcpy(pos, context, context_len);
561*0d69f216Schristos 	}
562*0d69f216Schristos 
563*0d69f216Schristos 	res = tls_prf(conn->rl.tls_version,
56462a52023Schristos 		      conn->master_secret, TLS_MASTER_SECRET_LEN,
565*0d69f216Schristos 		      label, seed, seed_len, out, out_len);
566*0d69f216Schristos 	os_free(seed);
567*0d69f216Schristos 	return res;
5688dbcf02cSchristos }
5698dbcf02cSchristos 
5708dbcf02cSchristos 
5718dbcf02cSchristos /**
5728dbcf02cSchristos  * tlsv1_client_get_cipher - Get current cipher name
5738dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
5748dbcf02cSchristos  * @buf: Buffer for the cipher name
5758dbcf02cSchristos  * @buflen: buf size
5768dbcf02cSchristos  * Returns: 0 on success, -1 on failure
5778dbcf02cSchristos  *
5788dbcf02cSchristos  * Get the name of the currently used cipher.
5798dbcf02cSchristos  */
tlsv1_client_get_cipher(struct tlsv1_client * conn,char * buf,size_t buflen)5808dbcf02cSchristos int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf,
5818dbcf02cSchristos 			    size_t buflen)
5828dbcf02cSchristos {
5838dbcf02cSchristos 	char *cipher;
5848dbcf02cSchristos 
5858dbcf02cSchristos 	switch (conn->rl.cipher_suite) {
5868dbcf02cSchristos 	case TLS_RSA_WITH_RC4_128_MD5:
5878dbcf02cSchristos 		cipher = "RC4-MD5";
5888dbcf02cSchristos 		break;
5898dbcf02cSchristos 	case TLS_RSA_WITH_RC4_128_SHA:
5908dbcf02cSchristos 		cipher = "RC4-SHA";
5918dbcf02cSchristos 		break;
5928dbcf02cSchristos 	case TLS_RSA_WITH_DES_CBC_SHA:
5938dbcf02cSchristos 		cipher = "DES-CBC-SHA";
5948dbcf02cSchristos 		break;
5958dbcf02cSchristos 	case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
5968dbcf02cSchristos 		cipher = "DES-CBC3-SHA";
5978dbcf02cSchristos 		break;
5989a53cbbeSchristos 	case TLS_DHE_RSA_WITH_DES_CBC_SHA:
5999a53cbbeSchristos 		cipher = "DHE-RSA-DES-CBC-SHA";
6009a53cbbeSchristos 		break;
6019a53cbbeSchristos 	case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
6029a53cbbeSchristos 		cipher = "DHE-RSA-DES-CBC3-SHA";
6039a53cbbeSchristos 		break;
6049a53cbbeSchristos 	case TLS_DH_anon_WITH_RC4_128_MD5:
6059a53cbbeSchristos 		cipher = "ADH-RC4-MD5";
6069a53cbbeSchristos 		break;
6079a53cbbeSchristos 	case TLS_DH_anon_WITH_DES_CBC_SHA:
6089a53cbbeSchristos 		cipher = "ADH-DES-SHA";
6099a53cbbeSchristos 		break;
6109a53cbbeSchristos 	case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
6119a53cbbeSchristos 		cipher = "ADH-DES-CBC3-SHA";
6129a53cbbeSchristos 		break;
6139a53cbbeSchristos 	case TLS_RSA_WITH_AES_128_CBC_SHA:
6149a53cbbeSchristos 		cipher = "AES-128-SHA";
6159a53cbbeSchristos 		break;
6169a53cbbeSchristos 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
6179a53cbbeSchristos 		cipher = "DHE-RSA-AES-128-SHA";
61862a52023Schristos 		break;
6198dbcf02cSchristos 	case TLS_DH_anon_WITH_AES_128_CBC_SHA:
6208dbcf02cSchristos 		cipher = "ADH-AES-128-SHA";
6218dbcf02cSchristos 		break;
6228dbcf02cSchristos 	case TLS_RSA_WITH_AES_256_CBC_SHA:
6238dbcf02cSchristos 		cipher = "AES-256-SHA";
6248dbcf02cSchristos 		break;
6259a53cbbeSchristos 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
6269a53cbbeSchristos 		cipher = "DHE-RSA-AES-256-SHA";
62762a52023Schristos 		break;
6289a53cbbeSchristos 	case TLS_DH_anon_WITH_AES_256_CBC_SHA:
6299a53cbbeSchristos 		cipher = "ADH-AES-256-SHA";
6308dbcf02cSchristos 		break;
63162a52023Schristos 	case TLS_RSA_WITH_AES_128_CBC_SHA256:
63262a52023Schristos 		cipher = "AES-128-SHA256";
63362a52023Schristos 		break;
6349a53cbbeSchristos 	case TLS_RSA_WITH_AES_256_CBC_SHA256:
6359a53cbbeSchristos 		cipher = "AES-256-SHA256";
6369a53cbbeSchristos 		break;
6379a53cbbeSchristos 	case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
6389a53cbbeSchristos 		cipher = "DHE-RSA-AES-128-SHA256";
6399a53cbbeSchristos 		break;
6409a53cbbeSchristos 	case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
6419a53cbbeSchristos 		cipher = "DHE-RSA-AES-256-SHA256";
6429a53cbbeSchristos 		break;
6439a53cbbeSchristos 	case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
6449a53cbbeSchristos 		cipher = "ADH-AES-128-SHA256";
6459a53cbbeSchristos 		break;
6469a53cbbeSchristos 	case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
6479a53cbbeSchristos 		cipher = "ADH-AES-256-SHA256";
6489a53cbbeSchristos 		break;
6498dbcf02cSchristos 	default:
6508dbcf02cSchristos 		return -1;
6518dbcf02cSchristos 	}
6528dbcf02cSchristos 
6538dbcf02cSchristos 	if (os_strlcpy(buf, cipher, buflen) >= buflen)
6548dbcf02cSchristos 		return -1;
6558dbcf02cSchristos 	return 0;
6568dbcf02cSchristos }
6578dbcf02cSchristos 
6588dbcf02cSchristos 
6598dbcf02cSchristos /**
6608dbcf02cSchristos  * tlsv1_client_shutdown - Shutdown TLS connection
6618dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
6628dbcf02cSchristos  * Returns: 0 on success, -1 on failure
6638dbcf02cSchristos  */
tlsv1_client_shutdown(struct tlsv1_client * conn)6648dbcf02cSchristos int tlsv1_client_shutdown(struct tlsv1_client *conn)
6658dbcf02cSchristos {
6668dbcf02cSchristos 	conn->state = CLIENT_HELLO;
6678dbcf02cSchristos 
6688dbcf02cSchristos 	if (tls_verify_hash_init(&conn->verify) < 0) {
6698dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
6708dbcf02cSchristos 			   "hash");
6718dbcf02cSchristos 		return -1;
6728dbcf02cSchristos 	}
6738dbcf02cSchristos 
6748dbcf02cSchristos 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
6758dbcf02cSchristos 	tlsv1_record_change_write_cipher(&conn->rl);
6768dbcf02cSchristos 	tlsv1_record_change_read_cipher(&conn->rl);
6778dbcf02cSchristos 
6788dbcf02cSchristos 	conn->certificate_requested = 0;
6798dbcf02cSchristos 	crypto_public_key_free(conn->server_rsa_key);
6808dbcf02cSchristos 	conn->server_rsa_key = NULL;
6818dbcf02cSchristos 	conn->session_resumed = 0;
6828dbcf02cSchristos 
6838dbcf02cSchristos 	return 0;
6848dbcf02cSchristos }
6858dbcf02cSchristos 
6868dbcf02cSchristos 
6878dbcf02cSchristos /**
6888dbcf02cSchristos  * tlsv1_client_resumed - Was session resumption used
6898dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
6908dbcf02cSchristos  * Returns: 1 if current session used session resumption, 0 if not
6918dbcf02cSchristos  */
tlsv1_client_resumed(struct tlsv1_client * conn)6928dbcf02cSchristos int tlsv1_client_resumed(struct tlsv1_client *conn)
6938dbcf02cSchristos {
6948dbcf02cSchristos 	return !!conn->session_resumed;
6958dbcf02cSchristos }
6968dbcf02cSchristos 
6978dbcf02cSchristos 
6988dbcf02cSchristos /**
6998dbcf02cSchristos  * tlsv1_client_hello_ext - Set TLS extension for ClientHello
7008dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
7018dbcf02cSchristos  * @ext_type: Extension type
7028dbcf02cSchristos  * @data: Extension payload (%NULL to remove extension)
7038dbcf02cSchristos  * @data_len: Extension payload length
7048dbcf02cSchristos  * Returns: 0 on success, -1 on failure
7058dbcf02cSchristos  */
tlsv1_client_hello_ext(struct tlsv1_client * conn,int ext_type,const u8 * data,size_t data_len)7068dbcf02cSchristos int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
7078dbcf02cSchristos 			   const u8 *data, size_t data_len)
7088dbcf02cSchristos {
7098dbcf02cSchristos 	u8 *pos;
7108dbcf02cSchristos 
7118dbcf02cSchristos 	conn->session_ticket_included = 0;
7128dbcf02cSchristos 	os_free(conn->client_hello_ext);
7138dbcf02cSchristos 	conn->client_hello_ext = NULL;
7148dbcf02cSchristos 	conn->client_hello_ext_len = 0;
7158dbcf02cSchristos 
7168dbcf02cSchristos 	if (data == NULL || data_len == 0)
7178dbcf02cSchristos 		return 0;
7188dbcf02cSchristos 
719928750b6Schristos 	pos = conn->client_hello_ext = os_malloc(4 + data_len);
7208dbcf02cSchristos 	if (pos == NULL)
7218dbcf02cSchristos 		return -1;
7228dbcf02cSchristos 
7238dbcf02cSchristos 	WPA_PUT_BE16(pos, ext_type);
7248dbcf02cSchristos 	pos += 2;
7258dbcf02cSchristos 	WPA_PUT_BE16(pos, data_len);
7268dbcf02cSchristos 	pos += 2;
7278dbcf02cSchristos 	os_memcpy(pos, data, data_len);
728928750b6Schristos 	conn->client_hello_ext_len = 4 + data_len;
7298dbcf02cSchristos 
7308dbcf02cSchristos 	if (ext_type == TLS_EXT_PAC_OPAQUE) {
7318dbcf02cSchristos 		conn->session_ticket_included = 1;
7328dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket");
7338dbcf02cSchristos 	}
7348dbcf02cSchristos 
7358dbcf02cSchristos 	return 0;
7368dbcf02cSchristos }
7378dbcf02cSchristos 
7388dbcf02cSchristos 
7398dbcf02cSchristos /**
740928750b6Schristos  * tlsv1_client_get_random - Get random data from TLS connection
7418dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
742928750b6Schristos  * @keys: Structure of random data (filled on success)
7438dbcf02cSchristos  * Returns: 0 on success, -1 on failure
7448dbcf02cSchristos  */
tlsv1_client_get_random(struct tlsv1_client * conn,struct tls_random * keys)745928750b6Schristos int tlsv1_client_get_random(struct tlsv1_client *conn, struct tls_random *keys)
7468dbcf02cSchristos {
7478dbcf02cSchristos 	os_memset(keys, 0, sizeof(*keys));
7488dbcf02cSchristos 	if (conn->state == CLIENT_HELLO)
7498dbcf02cSchristos 		return -1;
7508dbcf02cSchristos 
7518dbcf02cSchristos 	keys->client_random = conn->client_random;
7528dbcf02cSchristos 	keys->client_random_len = TLS_RANDOM_LEN;
7538dbcf02cSchristos 
7548dbcf02cSchristos 	if (conn->state != SERVER_HELLO) {
7558dbcf02cSchristos 		keys->server_random = conn->server_random;
7568dbcf02cSchristos 		keys->server_random_len = TLS_RANDOM_LEN;
7578dbcf02cSchristos 	}
7588dbcf02cSchristos 
7598dbcf02cSchristos 	return 0;
7608dbcf02cSchristos }
7618dbcf02cSchristos 
7628dbcf02cSchristos 
7638dbcf02cSchristos /**
7648dbcf02cSchristos  * tlsv1_client_get_keyblock_size - Get TLS key_block size
7658dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
7668dbcf02cSchristos  * Returns: Size of the key_block for the negotiated cipher suite or -1 on
7678dbcf02cSchristos  * failure
7688dbcf02cSchristos  */
tlsv1_client_get_keyblock_size(struct tlsv1_client * conn)7698dbcf02cSchristos int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn)
7708dbcf02cSchristos {
7718dbcf02cSchristos 	if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
7728dbcf02cSchristos 		return -1;
7738dbcf02cSchristos 
7748dbcf02cSchristos 	return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
7758dbcf02cSchristos 		    conn->rl.iv_size);
7768dbcf02cSchristos }
7778dbcf02cSchristos 
7788dbcf02cSchristos 
7798dbcf02cSchristos /**
7808dbcf02cSchristos  * tlsv1_client_set_cipher_list - Configure acceptable cipher suites
7818dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
7828dbcf02cSchristos  * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
7838dbcf02cSchristos  * (TLS_CIPHER_*).
7848dbcf02cSchristos  * Returns: 0 on success, -1 on failure
7858dbcf02cSchristos  */
tlsv1_client_set_cipher_list(struct tlsv1_client * conn,u8 * ciphers)7868dbcf02cSchristos int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
7878dbcf02cSchristos {
7888dbcf02cSchristos 	size_t count;
7898dbcf02cSchristos 	u16 *suites;
7908dbcf02cSchristos 
7918dbcf02cSchristos 	/* TODO: implement proper configuration of cipher suites */
7928dbcf02cSchristos 	if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
7938dbcf02cSchristos 		count = 0;
7948dbcf02cSchristos 		suites = conn->cipher_suites;
79562a52023Schristos 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256;
7968dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
79762a52023Schristos 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256;
7988dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
7998dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
8008dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
8018dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
8028dbcf02cSchristos 
8038dbcf02cSchristos 		/*
8048dbcf02cSchristos 		 * Cisco AP (at least 350 and 1200 series) local authentication
8058dbcf02cSchristos 		 * server does not know how to search cipher suites from the
8068dbcf02cSchristos 		 * list and seem to require that the last entry in the list is
8078dbcf02cSchristos 		 * the one that it wants to use. However, TLS specification
8088dbcf02cSchristos 		 * requires the list to be in the client preference order. As a
8098dbcf02cSchristos 		 * workaround, add anon-DH AES-128-SHA1 again at the end of the
8108dbcf02cSchristos 		 * list to allow the Cisco code to find it.
8118dbcf02cSchristos 		 */
8128dbcf02cSchristos 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
8138dbcf02cSchristos 		conn->num_cipher_suites = count;
8148dbcf02cSchristos 	}
8158dbcf02cSchristos 
8168dbcf02cSchristos 	return 0;
8178dbcf02cSchristos }
8188dbcf02cSchristos 
8198dbcf02cSchristos 
8208dbcf02cSchristos /**
8218dbcf02cSchristos  * tlsv1_client_set_cred - Set client credentials
8228dbcf02cSchristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
8238dbcf02cSchristos  * @cred: Credentials from tlsv1_cred_alloc()
8248dbcf02cSchristos  * Returns: 0 on success, -1 on failure
8258dbcf02cSchristos  *
8268dbcf02cSchristos  * On success, the client takes ownership of the credentials block and caller
8278dbcf02cSchristos  * must not free it. On failure, caller is responsible for freeing the
8288dbcf02cSchristos  * credential block.
8298dbcf02cSchristos  */
tlsv1_client_set_cred(struct tlsv1_client * conn,struct tlsv1_credentials * cred)8308dbcf02cSchristos int tlsv1_client_set_cred(struct tlsv1_client *conn,
8318dbcf02cSchristos 			  struct tlsv1_credentials *cred)
8328dbcf02cSchristos {
8338dbcf02cSchristos 	tlsv1_cred_free(conn->cred);
8348dbcf02cSchristos 	conn->cred = cred;
8358dbcf02cSchristos 	return 0;
8368dbcf02cSchristos }
8378dbcf02cSchristos 
8388dbcf02cSchristos 
839928750b6Schristos /**
840928750b6Schristos  * tlsv1_client_set_flags - Set connection flags
841928750b6Schristos  * @conn: TLSv1 client connection data from tlsv1_client_init()
842928750b6Schristos  * @flags: TLS_CONN_* bitfield
843928750b6Schristos  */
tlsv1_client_set_flags(struct tlsv1_client * conn,unsigned int flags)844928750b6Schristos void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
84542669be3Schristos {
846928750b6Schristos 	conn->flags = flags;
84742669be3Schristos }
84842669be3Schristos 
84942669be3Schristos 
tlsv1_client_set_session_ticket_cb(struct tlsv1_client * conn,tlsv1_client_session_ticket_cb cb,void * ctx)8508dbcf02cSchristos void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
8518dbcf02cSchristos 					tlsv1_client_session_ticket_cb cb,
8528dbcf02cSchristos 					void *ctx)
8538dbcf02cSchristos {
8548dbcf02cSchristos 	wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
8558dbcf02cSchristos 		   cb, ctx);
8568dbcf02cSchristos 	conn->session_ticket_cb = cb;
8578dbcf02cSchristos 	conn->session_ticket_cb_ctx = ctx;
8588dbcf02cSchristos }
859928750b6Schristos 
860928750b6Schristos 
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)861928750b6Schristos void tlsv1_client_set_cb(struct tlsv1_client *conn,
862928750b6Schristos 			 void (*event_cb)(void *ctx, enum tls_event ev,
863928750b6Schristos 					  union tls_event_data *data),
864928750b6Schristos 			 void *cb_ctx,
865928750b6Schristos 			 int cert_in_cb)
866928750b6Schristos {
867928750b6Schristos 	conn->event_cb = event_cb;
868928750b6Schristos 	conn->cb_ctx = cb_ctx;
869928750b6Schristos 	conn->cert_in_cb = !!cert_in_cb;
870928750b6Schristos }
871928750b6Schristos 
872928750b6Schristos 
tlsv1_client_get_version(struct tlsv1_client * conn,char * buf,size_t buflen)873928750b6Schristos int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
874928750b6Schristos 			     size_t buflen)
875928750b6Schristos {
876928750b6Schristos 	if (!conn)
877928750b6Schristos 		return -1;
878928750b6Schristos 	switch (conn->rl.tls_version) {
879928750b6Schristos 	case TLS_VERSION_1:
880928750b6Schristos 		os_strlcpy(buf, "TLSv1", buflen);
881928750b6Schristos 		break;
882928750b6Schristos 	case TLS_VERSION_1_1:
883928750b6Schristos 		os_strlcpy(buf, "TLSv1.1", buflen);
884928750b6Schristos 		break;
885928750b6Schristos 	case TLS_VERSION_1_2:
886928750b6Schristos 		os_strlcpy(buf, "TLSv1.2", buflen);
887928750b6Schristos 		break;
888928750b6Schristos 	default:
889928750b6Schristos 		return -1;
890928750b6Schristos 	}
891928750b6Schristos 
892928750b6Schristos 	return 0;
893928750b6Schristos }
894