xref: /dflybsd-src/contrib/wpa_supplicant/src/tls/tlsv1_client.c (revision 6d49e1aea1f916afb9e202b8d2ad09cfab6e48c3)
1*6d49e1aeSJan Lentfer /*
2*6d49e1aeSJan Lentfer  * TLSv1 client (RFC 2246)
3*6d49e1aeSJan Lentfer  * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
4*6d49e1aeSJan Lentfer  *
5*6d49e1aeSJan Lentfer  * This program is free software; you can redistribute it and/or modify
6*6d49e1aeSJan Lentfer  * it under the terms of the GNU General Public License version 2 as
7*6d49e1aeSJan Lentfer  * published by the Free Software Foundation.
8*6d49e1aeSJan Lentfer  *
9*6d49e1aeSJan Lentfer  * Alternatively, this software may be distributed under the terms of BSD
10*6d49e1aeSJan Lentfer  * license.
11*6d49e1aeSJan Lentfer  *
12*6d49e1aeSJan Lentfer  * See README and COPYING for more details.
13*6d49e1aeSJan Lentfer  */
14*6d49e1aeSJan Lentfer 
15*6d49e1aeSJan Lentfer #include "includes.h"
16*6d49e1aeSJan Lentfer 
17*6d49e1aeSJan Lentfer #include "common.h"
18*6d49e1aeSJan Lentfer #include "sha1.h"
19*6d49e1aeSJan Lentfer #include "tls.h"
20*6d49e1aeSJan Lentfer #include "tlsv1_common.h"
21*6d49e1aeSJan Lentfer #include "tlsv1_record.h"
22*6d49e1aeSJan Lentfer #include "tlsv1_client.h"
23*6d49e1aeSJan Lentfer #include "tlsv1_client_i.h"
24*6d49e1aeSJan Lentfer 
25*6d49e1aeSJan Lentfer /* TODO:
26*6d49e1aeSJan Lentfer  * Support for a message fragmented across several records (RFC 2246, 6.2.1)
27*6d49e1aeSJan Lentfer  */
28*6d49e1aeSJan Lentfer 
29*6d49e1aeSJan Lentfer 
30*6d49e1aeSJan Lentfer void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
31*6d49e1aeSJan Lentfer {
32*6d49e1aeSJan Lentfer 	conn->alert_level = level;
33*6d49e1aeSJan Lentfer 	conn->alert_description = description;
34*6d49e1aeSJan Lentfer }
35*6d49e1aeSJan Lentfer 
36*6d49e1aeSJan Lentfer 
37*6d49e1aeSJan Lentfer void tlsv1_client_free_dh(struct tlsv1_client *conn)
38*6d49e1aeSJan Lentfer {
39*6d49e1aeSJan Lentfer 	os_free(conn->dh_p);
40*6d49e1aeSJan Lentfer 	os_free(conn->dh_g);
41*6d49e1aeSJan Lentfer 	os_free(conn->dh_ys);
42*6d49e1aeSJan Lentfer 	conn->dh_p = conn->dh_g = conn->dh_ys = NULL;
43*6d49e1aeSJan Lentfer }
44*6d49e1aeSJan Lentfer 
45*6d49e1aeSJan Lentfer 
46*6d49e1aeSJan Lentfer int tls_derive_pre_master_secret(u8 *pre_master_secret)
47*6d49e1aeSJan Lentfer {
48*6d49e1aeSJan Lentfer 	WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
49*6d49e1aeSJan Lentfer 	if (os_get_random(pre_master_secret + 2,
50*6d49e1aeSJan Lentfer 			  TLS_PRE_MASTER_SECRET_LEN - 2))
51*6d49e1aeSJan Lentfer 		return -1;
52*6d49e1aeSJan Lentfer 	return 0;
53*6d49e1aeSJan Lentfer }
54*6d49e1aeSJan Lentfer 
55*6d49e1aeSJan Lentfer 
56*6d49e1aeSJan Lentfer int tls_derive_keys(struct tlsv1_client *conn,
57*6d49e1aeSJan Lentfer 		    const u8 *pre_master_secret, size_t pre_master_secret_len)
58*6d49e1aeSJan Lentfer {
59*6d49e1aeSJan Lentfer 	u8 seed[2 * TLS_RANDOM_LEN];
60*6d49e1aeSJan Lentfer 	u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
61*6d49e1aeSJan Lentfer 	u8 *pos;
62*6d49e1aeSJan Lentfer 	size_t key_block_len;
63*6d49e1aeSJan Lentfer 
64*6d49e1aeSJan Lentfer 	if (pre_master_secret) {
65*6d49e1aeSJan Lentfer 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
66*6d49e1aeSJan Lentfer 				pre_master_secret, pre_master_secret_len);
67*6d49e1aeSJan Lentfer 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
68*6d49e1aeSJan Lentfer 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
69*6d49e1aeSJan Lentfer 			  TLS_RANDOM_LEN);
70*6d49e1aeSJan Lentfer 		if (tls_prf(pre_master_secret, pre_master_secret_len,
71*6d49e1aeSJan Lentfer 			    "master secret", seed, 2 * TLS_RANDOM_LEN,
72*6d49e1aeSJan Lentfer 			    conn->master_secret, TLS_MASTER_SECRET_LEN)) {
73*6d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
74*6d49e1aeSJan Lentfer 				   "master_secret");
75*6d49e1aeSJan Lentfer 			return -1;
76*6d49e1aeSJan Lentfer 		}
77*6d49e1aeSJan Lentfer 		wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
78*6d49e1aeSJan Lentfer 				conn->master_secret, TLS_MASTER_SECRET_LEN);
79*6d49e1aeSJan Lentfer 	}
80*6d49e1aeSJan Lentfer 
81*6d49e1aeSJan Lentfer 	os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
82*6d49e1aeSJan Lentfer 	os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
83*6d49e1aeSJan Lentfer 	key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len +
84*6d49e1aeSJan Lentfer 			     conn->rl.iv_size);
85*6d49e1aeSJan Lentfer 	if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
86*6d49e1aeSJan Lentfer 		    "key expansion", seed, 2 * TLS_RANDOM_LEN,
87*6d49e1aeSJan Lentfer 		    key_block, key_block_len)) {
88*6d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
89*6d49e1aeSJan Lentfer 		return -1;
90*6d49e1aeSJan Lentfer 	}
91*6d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
92*6d49e1aeSJan Lentfer 			key_block, key_block_len);
93*6d49e1aeSJan Lentfer 
94*6d49e1aeSJan Lentfer 	pos = key_block;
95*6d49e1aeSJan Lentfer 
96*6d49e1aeSJan Lentfer 	/* client_write_MAC_secret */
97*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
98*6d49e1aeSJan Lentfer 	pos += conn->rl.hash_size;
99*6d49e1aeSJan Lentfer 	/* server_write_MAC_secret */
100*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
101*6d49e1aeSJan Lentfer 	pos += conn->rl.hash_size;
102*6d49e1aeSJan Lentfer 
103*6d49e1aeSJan Lentfer 	/* client_write_key */
104*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
105*6d49e1aeSJan Lentfer 	pos += conn->rl.key_material_len;
106*6d49e1aeSJan Lentfer 	/* server_write_key */
107*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
108*6d49e1aeSJan Lentfer 	pos += conn->rl.key_material_len;
109*6d49e1aeSJan Lentfer 
110*6d49e1aeSJan Lentfer 	/* client_write_IV */
111*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
112*6d49e1aeSJan Lentfer 	pos += conn->rl.iv_size;
113*6d49e1aeSJan Lentfer 	/* server_write_IV */
114*6d49e1aeSJan Lentfer 	os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
115*6d49e1aeSJan Lentfer 	pos += conn->rl.iv_size;
116*6d49e1aeSJan Lentfer 
117*6d49e1aeSJan Lentfer 	return 0;
118*6d49e1aeSJan Lentfer }
119*6d49e1aeSJan Lentfer 
120*6d49e1aeSJan Lentfer 
121*6d49e1aeSJan Lentfer /**
122*6d49e1aeSJan Lentfer  * tlsv1_client_handshake - Process TLS handshake
123*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
124*6d49e1aeSJan Lentfer  * @in_data: Input data from TLS peer
125*6d49e1aeSJan Lentfer  * @in_len: Input data length
126*6d49e1aeSJan Lentfer  * @out_len: Length of the output buffer.
127*6d49e1aeSJan Lentfer  * @appl_data: Pointer to application data pointer, or %NULL if dropped
128*6d49e1aeSJan Lentfer  * @appl_data_len: Pointer to variable that is set to appl_data length
129*6d49e1aeSJan Lentfer  * Returns: Pointer to output data, %NULL on failure
130*6d49e1aeSJan Lentfer  */
131*6d49e1aeSJan Lentfer u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
132*6d49e1aeSJan Lentfer 			    const u8 *in_data, size_t in_len,
133*6d49e1aeSJan Lentfer 			    size_t *out_len, u8 **appl_data,
134*6d49e1aeSJan Lentfer 			    size_t *appl_data_len)
135*6d49e1aeSJan Lentfer {
136*6d49e1aeSJan Lentfer 	const u8 *pos, *end;
137*6d49e1aeSJan Lentfer 	u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct;
138*6d49e1aeSJan Lentfer 	size_t in_msg_len;
139*6d49e1aeSJan Lentfer 	int no_appl_data;
140*6d49e1aeSJan Lentfer 
141*6d49e1aeSJan Lentfer 	if (conn->state == CLIENT_HELLO) {
142*6d49e1aeSJan Lentfer 		if (in_len)
143*6d49e1aeSJan Lentfer 			return NULL;
144*6d49e1aeSJan Lentfer 		return tls_send_client_hello(conn, out_len);
145*6d49e1aeSJan Lentfer 	}
146*6d49e1aeSJan Lentfer 
147*6d49e1aeSJan Lentfer 	if (in_data == NULL || in_len == 0)
148*6d49e1aeSJan Lentfer 		return NULL;
149*6d49e1aeSJan Lentfer 
150*6d49e1aeSJan Lentfer 	pos = in_data;
151*6d49e1aeSJan Lentfer 	end = in_data + in_len;
152*6d49e1aeSJan Lentfer 	in_msg = os_malloc(in_len);
153*6d49e1aeSJan Lentfer 	if (in_msg == NULL)
154*6d49e1aeSJan Lentfer 		return NULL;
155*6d49e1aeSJan Lentfer 
156*6d49e1aeSJan Lentfer 	/* Each received packet may include multiple records */
157*6d49e1aeSJan Lentfer 	while (pos < end) {
158*6d49e1aeSJan Lentfer 		in_msg_len = in_len;
159*6d49e1aeSJan Lentfer 		if (tlsv1_record_receive(&conn->rl, pos, end - pos,
160*6d49e1aeSJan Lentfer 					 in_msg, &in_msg_len, &alert)) {
161*6d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
162*6d49e1aeSJan Lentfer 				   "record failed");
163*6d49e1aeSJan Lentfer 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
164*6d49e1aeSJan Lentfer 			goto failed;
165*6d49e1aeSJan Lentfer 		}
166*6d49e1aeSJan Lentfer 		ct = pos[0];
167*6d49e1aeSJan Lentfer 
168*6d49e1aeSJan Lentfer 		in_pos = in_msg;
169*6d49e1aeSJan Lentfer 		in_end = in_msg + in_msg_len;
170*6d49e1aeSJan Lentfer 
171*6d49e1aeSJan Lentfer 		/* Each received record may include multiple messages of the
172*6d49e1aeSJan Lentfer 		 * same ContentType. */
173*6d49e1aeSJan Lentfer 		while (in_pos < in_end) {
174*6d49e1aeSJan Lentfer 			in_msg_len = in_end - in_pos;
175*6d49e1aeSJan Lentfer 			if (tlsv1_client_process_handshake(conn, ct, in_pos,
176*6d49e1aeSJan Lentfer 							   &in_msg_len,
177*6d49e1aeSJan Lentfer 							   appl_data,
178*6d49e1aeSJan Lentfer 							   appl_data_len) < 0)
179*6d49e1aeSJan Lentfer 				goto failed;
180*6d49e1aeSJan Lentfer 			in_pos += in_msg_len;
181*6d49e1aeSJan Lentfer 		}
182*6d49e1aeSJan Lentfer 
183*6d49e1aeSJan Lentfer 		pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
184*6d49e1aeSJan Lentfer 	}
185*6d49e1aeSJan Lentfer 
186*6d49e1aeSJan Lentfer 	os_free(in_msg);
187*6d49e1aeSJan Lentfer 	in_msg = NULL;
188*6d49e1aeSJan Lentfer 
189*6d49e1aeSJan Lentfer 	no_appl_data = appl_data == NULL || *appl_data == NULL;
190*6d49e1aeSJan Lentfer 	msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data);
191*6d49e1aeSJan Lentfer 
192*6d49e1aeSJan Lentfer failed:
193*6d49e1aeSJan Lentfer 	os_free(in_msg);
194*6d49e1aeSJan Lentfer 	if (conn->alert_level) {
195*6d49e1aeSJan Lentfer 		conn->state = FAILED;
196*6d49e1aeSJan Lentfer 		os_free(msg);
197*6d49e1aeSJan Lentfer 		msg = tlsv1_client_send_alert(conn, conn->alert_level,
198*6d49e1aeSJan Lentfer 					      conn->alert_description,
199*6d49e1aeSJan Lentfer 					      out_len);
200*6d49e1aeSJan Lentfer 	} else if (msg == NULL) {
201*6d49e1aeSJan Lentfer 		msg = os_zalloc(1);
202*6d49e1aeSJan Lentfer 		*out_len = 0;
203*6d49e1aeSJan Lentfer 	}
204*6d49e1aeSJan Lentfer 
205*6d49e1aeSJan Lentfer 	return msg;
206*6d49e1aeSJan Lentfer }
207*6d49e1aeSJan Lentfer 
208*6d49e1aeSJan Lentfer 
209*6d49e1aeSJan Lentfer /**
210*6d49e1aeSJan Lentfer  * tlsv1_client_encrypt - Encrypt data into TLS tunnel
211*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
212*6d49e1aeSJan Lentfer  * @in_data: Pointer to plaintext data to be encrypted
213*6d49e1aeSJan Lentfer  * @in_len: Input buffer length
214*6d49e1aeSJan Lentfer  * @out_data: Pointer to output buffer (encrypted TLS data)
215*6d49e1aeSJan Lentfer  * @out_len: Maximum out_data length
216*6d49e1aeSJan Lentfer  * Returns: Number of bytes written to out_data, -1 on failure
217*6d49e1aeSJan Lentfer  *
218*6d49e1aeSJan Lentfer  * This function is used after TLS handshake has been completed successfully to
219*6d49e1aeSJan Lentfer  * send data in the encrypted tunnel.
220*6d49e1aeSJan Lentfer  */
221*6d49e1aeSJan Lentfer int tlsv1_client_encrypt(struct tlsv1_client *conn,
222*6d49e1aeSJan Lentfer 			 const u8 *in_data, size_t in_len,
223*6d49e1aeSJan Lentfer 			 u8 *out_data, size_t out_len)
224*6d49e1aeSJan Lentfer {
225*6d49e1aeSJan Lentfer 	size_t rlen;
226*6d49e1aeSJan Lentfer 
227*6d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
228*6d49e1aeSJan Lentfer 			in_data, in_len);
229*6d49e1aeSJan Lentfer 
230*6d49e1aeSJan Lentfer 	os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len);
231*6d49e1aeSJan Lentfer 
232*6d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
233*6d49e1aeSJan Lentfer 			      out_data, out_len, in_len, &rlen) < 0) {
234*6d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
235*6d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
236*6d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
237*6d49e1aeSJan Lentfer 		return -1;
238*6d49e1aeSJan Lentfer 	}
239*6d49e1aeSJan Lentfer 
240*6d49e1aeSJan Lentfer 	return rlen;
241*6d49e1aeSJan Lentfer }
242*6d49e1aeSJan Lentfer 
243*6d49e1aeSJan Lentfer 
244*6d49e1aeSJan Lentfer /**
245*6d49e1aeSJan Lentfer  * tlsv1_client_decrypt - Decrypt data from TLS tunnel
246*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
247*6d49e1aeSJan Lentfer  * @in_data: Pointer to input buffer (encrypted TLS data)
248*6d49e1aeSJan Lentfer  * @in_len: Input buffer length
249*6d49e1aeSJan Lentfer  * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
250*6d49e1aeSJan Lentfer  * @out_len: Maximum out_data length
251*6d49e1aeSJan Lentfer  * Returns: Number of bytes written to out_data, -1 on failure
252*6d49e1aeSJan Lentfer  *
253*6d49e1aeSJan Lentfer  * This function is used after TLS handshake has been completed successfully to
254*6d49e1aeSJan Lentfer  * receive data from the encrypted tunnel.
255*6d49e1aeSJan Lentfer  */
256*6d49e1aeSJan Lentfer int tlsv1_client_decrypt(struct tlsv1_client *conn,
257*6d49e1aeSJan Lentfer 			 const u8 *in_data, size_t in_len,
258*6d49e1aeSJan Lentfer 			 u8 *out_data, size_t out_len)
259*6d49e1aeSJan Lentfer {
260*6d49e1aeSJan Lentfer 	const u8 *in_end, *pos;
261*6d49e1aeSJan Lentfer 	int res;
262*6d49e1aeSJan Lentfer 	u8 alert, *out_end, *out_pos;
263*6d49e1aeSJan Lentfer 	size_t olen;
264*6d49e1aeSJan Lentfer 
265*6d49e1aeSJan Lentfer 	pos = in_data;
266*6d49e1aeSJan Lentfer 	in_end = in_data + in_len;
267*6d49e1aeSJan Lentfer 	out_pos = out_data;
268*6d49e1aeSJan Lentfer 	out_end = out_data + out_len;
269*6d49e1aeSJan Lentfer 
270*6d49e1aeSJan Lentfer 	while (pos < in_end) {
271*6d49e1aeSJan Lentfer 		if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) {
272*6d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
273*6d49e1aeSJan Lentfer 				   "0x%x", pos[0]);
274*6d49e1aeSJan Lentfer 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
275*6d49e1aeSJan Lentfer 				  TLS_ALERT_UNEXPECTED_MESSAGE);
276*6d49e1aeSJan Lentfer 			return -1;
277*6d49e1aeSJan Lentfer 		}
278*6d49e1aeSJan Lentfer 
279*6d49e1aeSJan Lentfer 		olen = out_end - out_pos;
280*6d49e1aeSJan Lentfer 		res = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
281*6d49e1aeSJan Lentfer 					   out_pos, &olen, &alert);
282*6d49e1aeSJan Lentfer 		if (res < 0) {
283*6d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
284*6d49e1aeSJan Lentfer 				   "failed");
285*6d49e1aeSJan Lentfer 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
286*6d49e1aeSJan Lentfer 			return -1;
287*6d49e1aeSJan Lentfer 		}
288*6d49e1aeSJan Lentfer 		out_pos += olen;
289*6d49e1aeSJan Lentfer 		if (out_pos > out_end) {
290*6d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough "
291*6d49e1aeSJan Lentfer 				   "for processing the received record");
292*6d49e1aeSJan Lentfer 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
293*6d49e1aeSJan Lentfer 				  TLS_ALERT_INTERNAL_ERROR);
294*6d49e1aeSJan Lentfer 			return -1;
295*6d49e1aeSJan Lentfer 		}
296*6d49e1aeSJan Lentfer 
297*6d49e1aeSJan Lentfer 		pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3);
298*6d49e1aeSJan Lentfer 	}
299*6d49e1aeSJan Lentfer 
300*6d49e1aeSJan Lentfer 	return out_pos - out_data;
301*6d49e1aeSJan Lentfer }
302*6d49e1aeSJan Lentfer 
303*6d49e1aeSJan Lentfer 
304*6d49e1aeSJan Lentfer /**
305*6d49e1aeSJan Lentfer  * tlsv1_client_global_init - Initialize TLSv1 client
306*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
307*6d49e1aeSJan Lentfer  *
308*6d49e1aeSJan Lentfer  * This function must be called before using any other TLSv1 client functions.
309*6d49e1aeSJan Lentfer  */
310*6d49e1aeSJan Lentfer int tlsv1_client_global_init(void)
311*6d49e1aeSJan Lentfer {
312*6d49e1aeSJan Lentfer 	return crypto_global_init();
313*6d49e1aeSJan Lentfer }
314*6d49e1aeSJan Lentfer 
315*6d49e1aeSJan Lentfer 
316*6d49e1aeSJan Lentfer /**
317*6d49e1aeSJan Lentfer  * tlsv1_client_global_deinit - Deinitialize TLSv1 client
318*6d49e1aeSJan Lentfer  *
319*6d49e1aeSJan Lentfer  * This function can be used to deinitialize the TLSv1 client that was
320*6d49e1aeSJan Lentfer  * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions
321*6d49e1aeSJan Lentfer  * can be called after this before calling tlsv1_client_global_init() again.
322*6d49e1aeSJan Lentfer  */
323*6d49e1aeSJan Lentfer void tlsv1_client_global_deinit(void)
324*6d49e1aeSJan Lentfer {
325*6d49e1aeSJan Lentfer 	crypto_global_deinit();
326*6d49e1aeSJan Lentfer }
327*6d49e1aeSJan Lentfer 
328*6d49e1aeSJan Lentfer 
329*6d49e1aeSJan Lentfer /**
330*6d49e1aeSJan Lentfer  * tlsv1_client_init - Initialize TLSv1 client connection
331*6d49e1aeSJan Lentfer  * Returns: Pointer to TLSv1 client connection data or %NULL on failure
332*6d49e1aeSJan Lentfer  */
333*6d49e1aeSJan Lentfer struct tlsv1_client * tlsv1_client_init(void)
334*6d49e1aeSJan Lentfer {
335*6d49e1aeSJan Lentfer 	struct tlsv1_client *conn;
336*6d49e1aeSJan Lentfer 	size_t count;
337*6d49e1aeSJan Lentfer 	u16 *suites;
338*6d49e1aeSJan Lentfer 
339*6d49e1aeSJan Lentfer 	conn = os_zalloc(sizeof(*conn));
340*6d49e1aeSJan Lentfer 	if (conn == NULL)
341*6d49e1aeSJan Lentfer 		return NULL;
342*6d49e1aeSJan Lentfer 
343*6d49e1aeSJan Lentfer 	conn->state = CLIENT_HELLO;
344*6d49e1aeSJan Lentfer 
345*6d49e1aeSJan Lentfer 	if (tls_verify_hash_init(&conn->verify) < 0) {
346*6d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
347*6d49e1aeSJan Lentfer 			   "hash");
348*6d49e1aeSJan Lentfer 		os_free(conn);
349*6d49e1aeSJan Lentfer 		return NULL;
350*6d49e1aeSJan Lentfer 	}
351*6d49e1aeSJan Lentfer 
352*6d49e1aeSJan Lentfer 	count = 0;
353*6d49e1aeSJan Lentfer 	suites = conn->cipher_suites;
354*6d49e1aeSJan Lentfer #ifndef CONFIG_CRYPTO_INTERNAL
355*6d49e1aeSJan Lentfer 	suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
356*6d49e1aeSJan Lentfer #endif /* CONFIG_CRYPTO_INTERNAL */
357*6d49e1aeSJan Lentfer 	suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
358*6d49e1aeSJan Lentfer 	suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
359*6d49e1aeSJan Lentfer 	suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
360*6d49e1aeSJan Lentfer 	suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
361*6d49e1aeSJan Lentfer 	conn->num_cipher_suites = count;
362*6d49e1aeSJan Lentfer 
363*6d49e1aeSJan Lentfer 	return conn;
364*6d49e1aeSJan Lentfer }
365*6d49e1aeSJan Lentfer 
366*6d49e1aeSJan Lentfer 
367*6d49e1aeSJan Lentfer /**
368*6d49e1aeSJan Lentfer  * tlsv1_client_deinit - Deinitialize TLSv1 client connection
369*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
370*6d49e1aeSJan Lentfer  */
371*6d49e1aeSJan Lentfer void tlsv1_client_deinit(struct tlsv1_client *conn)
372*6d49e1aeSJan Lentfer {
373*6d49e1aeSJan Lentfer 	crypto_public_key_free(conn->server_rsa_key);
374*6d49e1aeSJan Lentfer 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
375*6d49e1aeSJan Lentfer 	tlsv1_record_change_write_cipher(&conn->rl);
376*6d49e1aeSJan Lentfer 	tlsv1_record_change_read_cipher(&conn->rl);
377*6d49e1aeSJan Lentfer 	tls_verify_hash_free(&conn->verify);
378*6d49e1aeSJan Lentfer 	os_free(conn->client_hello_ext);
379*6d49e1aeSJan Lentfer 	tlsv1_client_free_dh(conn);
380*6d49e1aeSJan Lentfer 	tlsv1_cred_free(conn->cred);
381*6d49e1aeSJan Lentfer 	os_free(conn);
382*6d49e1aeSJan Lentfer }
383*6d49e1aeSJan Lentfer 
384*6d49e1aeSJan Lentfer 
385*6d49e1aeSJan Lentfer /**
386*6d49e1aeSJan Lentfer  * tlsv1_client_established - Check whether connection has been established
387*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
388*6d49e1aeSJan Lentfer  * Returns: 1 if connection is established, 0 if not
389*6d49e1aeSJan Lentfer  */
390*6d49e1aeSJan Lentfer int tlsv1_client_established(struct tlsv1_client *conn)
391*6d49e1aeSJan Lentfer {
392*6d49e1aeSJan Lentfer 	return conn->state == ESTABLISHED;
393*6d49e1aeSJan Lentfer }
394*6d49e1aeSJan Lentfer 
395*6d49e1aeSJan Lentfer 
396*6d49e1aeSJan Lentfer /**
397*6d49e1aeSJan Lentfer  * tlsv1_client_prf - Use TLS-PRF to derive keying material
398*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
399*6d49e1aeSJan Lentfer  * @label: Label (e.g., description of the key) for PRF
400*6d49e1aeSJan Lentfer  * @server_random_first: seed is 0 = client_random|server_random,
401*6d49e1aeSJan Lentfer  * 1 = server_random|client_random
402*6d49e1aeSJan Lentfer  * @out: Buffer for output data from TLS-PRF
403*6d49e1aeSJan Lentfer  * @out_len: Length of the output buffer
404*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
405*6d49e1aeSJan Lentfer  */
406*6d49e1aeSJan Lentfer int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
407*6d49e1aeSJan Lentfer 		     int server_random_first, u8 *out, size_t out_len)
408*6d49e1aeSJan Lentfer {
409*6d49e1aeSJan Lentfer 	u8 seed[2 * TLS_RANDOM_LEN];
410*6d49e1aeSJan Lentfer 
411*6d49e1aeSJan Lentfer 	if (conn->state != ESTABLISHED)
412*6d49e1aeSJan Lentfer 		return -1;
413*6d49e1aeSJan Lentfer 
414*6d49e1aeSJan Lentfer 	if (server_random_first) {
415*6d49e1aeSJan Lentfer 		os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
416*6d49e1aeSJan Lentfer 		os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
417*6d49e1aeSJan Lentfer 			  TLS_RANDOM_LEN);
418*6d49e1aeSJan Lentfer 	} else {
419*6d49e1aeSJan Lentfer 		os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
420*6d49e1aeSJan Lentfer 		os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
421*6d49e1aeSJan Lentfer 			  TLS_RANDOM_LEN);
422*6d49e1aeSJan Lentfer 	}
423*6d49e1aeSJan Lentfer 
424*6d49e1aeSJan Lentfer 	return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
425*6d49e1aeSJan Lentfer 		       label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
426*6d49e1aeSJan Lentfer }
427*6d49e1aeSJan Lentfer 
428*6d49e1aeSJan Lentfer 
429*6d49e1aeSJan Lentfer /**
430*6d49e1aeSJan Lentfer  * tlsv1_client_get_cipher - Get current cipher name
431*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
432*6d49e1aeSJan Lentfer  * @buf: Buffer for the cipher name
433*6d49e1aeSJan Lentfer  * @buflen: buf size
434*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
435*6d49e1aeSJan Lentfer  *
436*6d49e1aeSJan Lentfer  * Get the name of the currently used cipher.
437*6d49e1aeSJan Lentfer  */
438*6d49e1aeSJan Lentfer int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf,
439*6d49e1aeSJan Lentfer 			    size_t buflen)
440*6d49e1aeSJan Lentfer {
441*6d49e1aeSJan Lentfer 	char *cipher;
442*6d49e1aeSJan Lentfer 
443*6d49e1aeSJan Lentfer 	switch (conn->rl.cipher_suite) {
444*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_RC4_128_MD5:
445*6d49e1aeSJan Lentfer 		cipher = "RC4-MD5";
446*6d49e1aeSJan Lentfer 		break;
447*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_RC4_128_SHA:
448*6d49e1aeSJan Lentfer 		cipher = "RC4-SHA";
449*6d49e1aeSJan Lentfer 		break;
450*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_DES_CBC_SHA:
451*6d49e1aeSJan Lentfer 		cipher = "DES-CBC-SHA";
452*6d49e1aeSJan Lentfer 		break;
453*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
454*6d49e1aeSJan Lentfer 		cipher = "DES-CBC3-SHA";
455*6d49e1aeSJan Lentfer 		break;
456*6d49e1aeSJan Lentfer 	case TLS_DH_anon_WITH_AES_128_CBC_SHA:
457*6d49e1aeSJan Lentfer 		cipher = "ADH-AES-128-SHA";
458*6d49e1aeSJan Lentfer 		break;
459*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_AES_256_CBC_SHA:
460*6d49e1aeSJan Lentfer 		cipher = "AES-256-SHA";
461*6d49e1aeSJan Lentfer 		break;
462*6d49e1aeSJan Lentfer 	case TLS_RSA_WITH_AES_128_CBC_SHA:
463*6d49e1aeSJan Lentfer 		cipher = "AES-128-SHA";
464*6d49e1aeSJan Lentfer 		break;
465*6d49e1aeSJan Lentfer 	default:
466*6d49e1aeSJan Lentfer 		return -1;
467*6d49e1aeSJan Lentfer 	}
468*6d49e1aeSJan Lentfer 
469*6d49e1aeSJan Lentfer 	if (os_strlcpy(buf, cipher, buflen) >= buflen)
470*6d49e1aeSJan Lentfer 		return -1;
471*6d49e1aeSJan Lentfer 	return 0;
472*6d49e1aeSJan Lentfer }
473*6d49e1aeSJan Lentfer 
474*6d49e1aeSJan Lentfer 
475*6d49e1aeSJan Lentfer /**
476*6d49e1aeSJan Lentfer  * tlsv1_client_shutdown - Shutdown TLS connection
477*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
478*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
479*6d49e1aeSJan Lentfer  */
480*6d49e1aeSJan Lentfer int tlsv1_client_shutdown(struct tlsv1_client *conn)
481*6d49e1aeSJan Lentfer {
482*6d49e1aeSJan Lentfer 	conn->state = CLIENT_HELLO;
483*6d49e1aeSJan Lentfer 
484*6d49e1aeSJan Lentfer 	if (tls_verify_hash_init(&conn->verify) < 0) {
485*6d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
486*6d49e1aeSJan Lentfer 			   "hash");
487*6d49e1aeSJan Lentfer 		return -1;
488*6d49e1aeSJan Lentfer 	}
489*6d49e1aeSJan Lentfer 
490*6d49e1aeSJan Lentfer 	tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
491*6d49e1aeSJan Lentfer 	tlsv1_record_change_write_cipher(&conn->rl);
492*6d49e1aeSJan Lentfer 	tlsv1_record_change_read_cipher(&conn->rl);
493*6d49e1aeSJan Lentfer 
494*6d49e1aeSJan Lentfer 	conn->certificate_requested = 0;
495*6d49e1aeSJan Lentfer 	crypto_public_key_free(conn->server_rsa_key);
496*6d49e1aeSJan Lentfer 	conn->server_rsa_key = NULL;
497*6d49e1aeSJan Lentfer 	conn->session_resumed = 0;
498*6d49e1aeSJan Lentfer 
499*6d49e1aeSJan Lentfer 	return 0;
500*6d49e1aeSJan Lentfer }
501*6d49e1aeSJan Lentfer 
502*6d49e1aeSJan Lentfer 
503*6d49e1aeSJan Lentfer /**
504*6d49e1aeSJan Lentfer  * tlsv1_client_resumed - Was session resumption used
505*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
506*6d49e1aeSJan Lentfer  * Returns: 1 if current session used session resumption, 0 if not
507*6d49e1aeSJan Lentfer  */
508*6d49e1aeSJan Lentfer int tlsv1_client_resumed(struct tlsv1_client *conn)
509*6d49e1aeSJan Lentfer {
510*6d49e1aeSJan Lentfer 	return !!conn->session_resumed;
511*6d49e1aeSJan Lentfer }
512*6d49e1aeSJan Lentfer 
513*6d49e1aeSJan Lentfer 
514*6d49e1aeSJan Lentfer /**
515*6d49e1aeSJan Lentfer  * tlsv1_client_hello_ext - Set TLS extension for ClientHello
516*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
517*6d49e1aeSJan Lentfer  * @ext_type: Extension type
518*6d49e1aeSJan Lentfer  * @data: Extension payload (%NULL to remove extension)
519*6d49e1aeSJan Lentfer  * @data_len: Extension payload length
520*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
521*6d49e1aeSJan Lentfer  */
522*6d49e1aeSJan Lentfer int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
523*6d49e1aeSJan Lentfer 			   const u8 *data, size_t data_len)
524*6d49e1aeSJan Lentfer {
525*6d49e1aeSJan Lentfer 	u8 *pos;
526*6d49e1aeSJan Lentfer 
527*6d49e1aeSJan Lentfer 	conn->session_ticket_included = 0;
528*6d49e1aeSJan Lentfer 	os_free(conn->client_hello_ext);
529*6d49e1aeSJan Lentfer 	conn->client_hello_ext = NULL;
530*6d49e1aeSJan Lentfer 	conn->client_hello_ext_len = 0;
531*6d49e1aeSJan Lentfer 
532*6d49e1aeSJan Lentfer 	if (data == NULL || data_len == 0)
533*6d49e1aeSJan Lentfer 		return 0;
534*6d49e1aeSJan Lentfer 
535*6d49e1aeSJan Lentfer 	pos = conn->client_hello_ext = os_malloc(6 + data_len);
536*6d49e1aeSJan Lentfer 	if (pos == NULL)
537*6d49e1aeSJan Lentfer 		return -1;
538*6d49e1aeSJan Lentfer 
539*6d49e1aeSJan Lentfer 	WPA_PUT_BE16(pos, 4 + data_len);
540*6d49e1aeSJan Lentfer 	pos += 2;
541*6d49e1aeSJan Lentfer 	WPA_PUT_BE16(pos, ext_type);
542*6d49e1aeSJan Lentfer 	pos += 2;
543*6d49e1aeSJan Lentfer 	WPA_PUT_BE16(pos, data_len);
544*6d49e1aeSJan Lentfer 	pos += 2;
545*6d49e1aeSJan Lentfer 	os_memcpy(pos, data, data_len);
546*6d49e1aeSJan Lentfer 	conn->client_hello_ext_len = 6 + data_len;
547*6d49e1aeSJan Lentfer 
548*6d49e1aeSJan Lentfer 	if (ext_type == TLS_EXT_PAC_OPAQUE) {
549*6d49e1aeSJan Lentfer 		conn->session_ticket_included = 1;
550*6d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket");
551*6d49e1aeSJan Lentfer 	}
552*6d49e1aeSJan Lentfer 
553*6d49e1aeSJan Lentfer 	return 0;
554*6d49e1aeSJan Lentfer }
555*6d49e1aeSJan Lentfer 
556*6d49e1aeSJan Lentfer 
557*6d49e1aeSJan Lentfer /**
558*6d49e1aeSJan Lentfer  * tlsv1_client_get_keys - Get master key and random data from TLS connection
559*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
560*6d49e1aeSJan Lentfer  * @keys: Structure of key/random data (filled on success)
561*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
562*6d49e1aeSJan Lentfer  */
563*6d49e1aeSJan Lentfer int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys)
564*6d49e1aeSJan Lentfer {
565*6d49e1aeSJan Lentfer 	os_memset(keys, 0, sizeof(*keys));
566*6d49e1aeSJan Lentfer 	if (conn->state == CLIENT_HELLO)
567*6d49e1aeSJan Lentfer 		return -1;
568*6d49e1aeSJan Lentfer 
569*6d49e1aeSJan Lentfer 	keys->client_random = conn->client_random;
570*6d49e1aeSJan Lentfer 	keys->client_random_len = TLS_RANDOM_LEN;
571*6d49e1aeSJan Lentfer 
572*6d49e1aeSJan Lentfer 	if (conn->state != SERVER_HELLO) {
573*6d49e1aeSJan Lentfer 		keys->server_random = conn->server_random;
574*6d49e1aeSJan Lentfer 		keys->server_random_len = TLS_RANDOM_LEN;
575*6d49e1aeSJan Lentfer 		keys->master_key = conn->master_secret;
576*6d49e1aeSJan Lentfer 		keys->master_key_len = TLS_MASTER_SECRET_LEN;
577*6d49e1aeSJan Lentfer 	}
578*6d49e1aeSJan Lentfer 
579*6d49e1aeSJan Lentfer 	return 0;
580*6d49e1aeSJan Lentfer }
581*6d49e1aeSJan Lentfer 
582*6d49e1aeSJan Lentfer 
583*6d49e1aeSJan Lentfer /**
584*6d49e1aeSJan Lentfer  * tlsv1_client_get_keyblock_size - Get TLS key_block size
585*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
586*6d49e1aeSJan Lentfer  * Returns: Size of the key_block for the negotiated cipher suite or -1 on
587*6d49e1aeSJan Lentfer  * failure
588*6d49e1aeSJan Lentfer  */
589*6d49e1aeSJan Lentfer int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn)
590*6d49e1aeSJan Lentfer {
591*6d49e1aeSJan Lentfer 	if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
592*6d49e1aeSJan Lentfer 		return -1;
593*6d49e1aeSJan Lentfer 
594*6d49e1aeSJan Lentfer 	return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
595*6d49e1aeSJan Lentfer 		    conn->rl.iv_size);
596*6d49e1aeSJan Lentfer }
597*6d49e1aeSJan Lentfer 
598*6d49e1aeSJan Lentfer 
599*6d49e1aeSJan Lentfer /**
600*6d49e1aeSJan Lentfer  * tlsv1_client_set_cipher_list - Configure acceptable cipher suites
601*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
602*6d49e1aeSJan Lentfer  * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
603*6d49e1aeSJan Lentfer  * (TLS_CIPHER_*).
604*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
605*6d49e1aeSJan Lentfer  */
606*6d49e1aeSJan Lentfer int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
607*6d49e1aeSJan Lentfer {
608*6d49e1aeSJan Lentfer #ifdef EAP_FAST
609*6d49e1aeSJan Lentfer 	size_t count;
610*6d49e1aeSJan Lentfer 	u16 *suites;
611*6d49e1aeSJan Lentfer 
612*6d49e1aeSJan Lentfer 	/* TODO: implement proper configuration of cipher suites */
613*6d49e1aeSJan Lentfer 	if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
614*6d49e1aeSJan Lentfer 		count = 0;
615*6d49e1aeSJan Lentfer 		suites = conn->cipher_suites;
616*6d49e1aeSJan Lentfer #ifndef CONFIG_CRYPTO_INTERNAL
617*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
618*6d49e1aeSJan Lentfer #endif /* CONFIG_CRYPTO_INTERNAL */
619*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
620*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
621*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
622*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
623*6d49e1aeSJan Lentfer 
624*6d49e1aeSJan Lentfer 		/*
625*6d49e1aeSJan Lentfer 		 * Cisco AP (at least 350 and 1200 series) local authentication
626*6d49e1aeSJan Lentfer 		 * server does not know how to search cipher suites from the
627*6d49e1aeSJan Lentfer 		 * list and seem to require that the last entry in the list is
628*6d49e1aeSJan Lentfer 		 * the one that it wants to use. However, TLS specification
629*6d49e1aeSJan Lentfer 		 * requires the list to be in the client preference order. As a
630*6d49e1aeSJan Lentfer 		 * workaround, add anon-DH AES-128-SHA1 again at the end of the
631*6d49e1aeSJan Lentfer 		 * list to allow the Cisco code to find it.
632*6d49e1aeSJan Lentfer 		 */
633*6d49e1aeSJan Lentfer 		suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
634*6d49e1aeSJan Lentfer 		conn->num_cipher_suites = count;
635*6d49e1aeSJan Lentfer 	}
636*6d49e1aeSJan Lentfer 
637*6d49e1aeSJan Lentfer 	return 0;
638*6d49e1aeSJan Lentfer #else /* EAP_FAST */
639*6d49e1aeSJan Lentfer 	return -1;
640*6d49e1aeSJan Lentfer #endif /* EAP_FAST */
641*6d49e1aeSJan Lentfer }
642*6d49e1aeSJan Lentfer 
643*6d49e1aeSJan Lentfer 
644*6d49e1aeSJan Lentfer /**
645*6d49e1aeSJan Lentfer  * tlsv1_client_set_cred - Set client credentials
646*6d49e1aeSJan Lentfer  * @conn: TLSv1 client connection data from tlsv1_client_init()
647*6d49e1aeSJan Lentfer  * @cred: Credentials from tlsv1_cred_alloc()
648*6d49e1aeSJan Lentfer  * Returns: 0 on success, -1 on failure
649*6d49e1aeSJan Lentfer  *
650*6d49e1aeSJan Lentfer  * On success, the client takes ownership of the credentials block and caller
651*6d49e1aeSJan Lentfer  * must not free it. On failure, caller is responsible for freeing the
652*6d49e1aeSJan Lentfer  * credential block.
653*6d49e1aeSJan Lentfer  */
654*6d49e1aeSJan Lentfer int tlsv1_client_set_cred(struct tlsv1_client *conn,
655*6d49e1aeSJan Lentfer 			  struct tlsv1_credentials *cred)
656*6d49e1aeSJan Lentfer {
657*6d49e1aeSJan Lentfer 	tlsv1_cred_free(conn->cred);
658*6d49e1aeSJan Lentfer 	conn->cred = cred;
659*6d49e1aeSJan Lentfer 	return 0;
660*6d49e1aeSJan Lentfer }
661*6d49e1aeSJan Lentfer 
662*6d49e1aeSJan Lentfer 
663*6d49e1aeSJan Lentfer void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
664*6d49e1aeSJan Lentfer 					tlsv1_client_session_ticket_cb cb,
665*6d49e1aeSJan Lentfer 					void *ctx)
666*6d49e1aeSJan Lentfer {
667*6d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
668*6d49e1aeSJan Lentfer 		   cb, ctx);
669*6d49e1aeSJan Lentfer 	conn->session_ticket_cb = cb;
670*6d49e1aeSJan Lentfer 	conn->session_ticket_cb_ctx = ctx;
671*6d49e1aeSJan Lentfer }
672