1 /*
2  * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
3  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 #include "utils/includes.h"
9 
10 #ifdef EAP_PEAP
11 #include "utils/common.h"
12 #include "crypto/sha1.h"
13 #include "crypto/tls.h"
14 #include "eap_peer/eap_tlv_common.h"
15 #include "eap_peer/eap_peap_common.h"
16 #include "eap_peer/eap_i.h"
17 #include "eap_peer/eap_tls_common.h"
18 #include "eap_peer/eap_config.h"
19 #include "eap_peer/eap_methods.h"
20 
21 /* Maximum supported PEAP version
22  * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
23  * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
24  * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
25  */
26 #define EAP_PEAP_VERSION 1
27 
28 
29 static void eap_peap_deinit(struct eap_sm *sm, void *priv);
30 
31 
32 struct eap_peap_data {
33 	struct eap_ssl_data ssl;
34 
35 	int peap_version, force_peap_version, force_new_label;
36 
37 	const struct eap_method *phase2_method;
38 	void *phase2_priv;
39 	int phase2_success;
40 	int phase2_eap_success;
41 	int phase2_eap_started;
42 
43 	struct eap_method_type phase2_type;
44 	struct eap_method_type *phase2_types;
45 	size_t num_phase2_types;
46 
47 	int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
48 				 * EAP-Success
49 				 * 1 = reply with tunneled EAP-Success to inner
50 				 * EAP-Success and expect AS to send outer
51 				 * (unencrypted) EAP-Success after this
52 				 * 2 = reply with PEAP/TLS ACK to inner
53 				 * EAP-Success and expect AS to send outer
54 				 * (unencrypted) EAP-Success after this */
55 	int resuming; /* starting a resumed session */
56 	int reauth; /* reauthentication */
57 	u8 *key_data;
58 	u8 *session_id;
59 	size_t id_len;
60 
61 	struct wpabuf *pending_phase2_req;
62 	enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
63 	int crypto_binding_used;
64 	u8 binding_nonce[32];
65 	u8 ipmk[40];
66 	u8 cmk[20];
67 	int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP)
68 		  * is enabled. */
69 	enum { NO_AUTH, FOR_INITIAL, ALWAYS } phase2_auth;
70 };
71 
72 
73 static int
eap_peap_parse_phase1(struct eap_peap_data * data,const char * phase1)74 eap_peap_parse_phase1(struct eap_peap_data *data,
75 		      const char *phase1)
76 {
77 	const char *pos;
78 
79 	pos = os_strstr(phase1, "peapver=");
80 	if (pos) {
81 		data->force_peap_version = atoi(pos + 8);
82 		data->peap_version = data->force_peap_version;
83 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d",
84 			   data->force_peap_version);
85 	}
86 
87 	if (os_strstr(phase1, "peaplabel=1")) {
88 		data->force_new_label = 1;
89 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key "
90 			   "derivation");
91 	}
92 
93 	if (os_strstr(phase1, "peap_outer_success=0")) {
94 		data->peap_outer_success = 0;
95 		wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on "
96 			   "tunneled EAP-Success");
97 	} else if (os_strstr(phase1, "peap_outer_success=1")) {
98 		data->peap_outer_success = 1;
99 		wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success "
100 			   "after receiving tunneled EAP-Success");
101 	} else if (os_strstr(phase1, "peap_outer_success=2")) {
102 		data->peap_outer_success = 2;
103 		wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after "
104 			   "receiving tunneled EAP-Success");
105 	}
106 
107 	if (os_strstr(phase1, "crypto_binding=0")) {
108 		data->crypto_binding = NO_BINDING;
109 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
110 	} else if (os_strstr(phase1, "crypto_binding=1")) {
111 		data->crypto_binding = OPTIONAL_BINDING;
112 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
113 	} else if (os_strstr(phase1, "crypto_binding=2")) {
114 		data->crypto_binding = REQUIRE_BINDING;
115 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
116 	}
117 
118 	if (os_strstr(phase1, "phase2_auth=0")) {
119 		data->phase2_auth = NO_AUTH;
120 		wpa_printf(MSG_DEBUG,
121 			   "EAP-PEAP: Do not require Phase 2 authentication");
122 	} else if (os_strstr(phase1, "phase2_auth=1")) {
123 		data->phase2_auth = FOR_INITIAL;
124 		wpa_printf(MSG_DEBUG,
125 			   "EAP-PEAP: Require Phase 2 authentication for initial connection");
126 	} else if (os_strstr(phase1, "phase2_auth=2")) {
127 		data->phase2_auth = ALWAYS;
128 		wpa_printf(MSG_DEBUG,
129 			   "EAP-PEAP: Require Phase 2 authentication for all cases");
130 	}
131 #ifdef EAP_TNC
132 	if (os_strstr(phase1, "tnc=soh2")) {
133 		data->soh = 2;
134 		wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
135 	} else if (os_strstr(phase1, "tnc=soh1")) {
136 		data->soh = 1;
137 		wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled");
138 	} else if (os_strstr(phase1, "tnc=soh")) {
139 		data->soh = 2;
140 		wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
141 	}
142 #endif /* EAP_TNC */
143 
144 	return 0;
145 }
146 
147 
148 static void *
eap_peap_init(struct eap_sm * sm)149 eap_peap_init(struct eap_sm *sm)
150 {
151 	struct eap_peap_data *data;
152 	struct eap_peer_config *config = eap_get_config(sm);
153 
154 	data = (struct eap_peap_data *)os_zalloc(sizeof(*data));
155 	if (data == NULL)
156 		return NULL;
157 	sm->peap_done = FALSE;
158 	data->peap_version = EAP_PEAP_VERSION;
159 	data->force_peap_version = -1;
160 	data->peap_outer_success = 2;
161 	data->crypto_binding = OPTIONAL_BINDING;
162 	data->phase2_auth = FOR_INITIAL;
163 
164 	if (config && config->phase1 &&
165 	    eap_peap_parse_phase1(data, config->phase1) < 0) {
166 		eap_peap_deinit(sm, data);
167 		return NULL;
168 	}
169 
170 	if (eap_peer_select_phase2_methods(config, "auth=",
171 					   &data->phase2_types,
172 					   &data->num_phase2_types) < 0) {
173 		eap_peap_deinit(sm, data);
174 		return NULL;
175 	}
176 
177 	data->phase2_type.vendor = EAP_VENDOR_IETF;
178 	data->phase2_type.method = EAP_TYPE_NONE;
179 
180 	if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_PEAP)) {
181 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
182 		eap_peap_deinit(sm, data);
183 		return NULL;
184 	}
185 
186 	return data;
187 }
188 
189 
190 static void
eap_peap_deinit(struct eap_sm * sm,void * priv)191 eap_peap_deinit(struct eap_sm *sm, void *priv)
192 {
193 	struct eap_peap_data *data = priv;
194 	if (data == NULL)
195 		return;
196 	if (data->phase2_priv && data->phase2_method)
197 		data->phase2_method->deinit(sm, data->phase2_priv);
198 	os_free(data->phase2_types);
199 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
200 	os_free(data->key_data);
201 	os_free(data->session_id);
202 	wpabuf_free(data->pending_phase2_req);
203 	os_free(data);
204 }
205 
206 
207 /**
208  * eap_tlv_build_nak - Build EAP-TLV NAK message
209  * @id: EAP identifier for the header
210  * @nak_type: TLV type (EAP_TLV_*)
211  * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
212  *
213  * This function builds an EAP-TLV NAK message. The caller is responsible for
214  * freeing the returned buffer.
215  */
216 static struct wpabuf *
eap_tlv_build_nak(int id,u16 nak_type)217 eap_tlv_build_nak(int id, u16 nak_type)
218 {
219 	struct wpabuf *msg;
220 
221 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
222 			    EAP_CODE_RESPONSE, id);
223 	if (msg == NULL)
224 		return NULL;
225 
226 	wpabuf_put_u8(msg, 0x80); /* Mandatory */
227 	wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
228 	wpabuf_put_be16(msg, 6); /* Length */
229 	wpabuf_put_be32(msg, 0); /* Vendor-Id */
230 	wpabuf_put_be16(msg, nak_type); /* NAK-Type */
231 
232 	return msg;
233 }
234 
235 
236 static int
eap_peap_get_isk(struct eap_sm * sm,struct eap_peap_data * data,u8 * isk,size_t isk_len)237 eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
238 		 u8 *isk, size_t isk_len)
239 {
240 	u8 *key;
241 	size_t key_len;
242 
243 	os_memset(isk, 0, isk_len);
244 	if (data->phase2_method == NULL || data->phase2_priv == NULL ||
245 	    data->phase2_method->isKeyAvailable == NULL ||
246 	    data->phase2_method->getKey == NULL)
247 		return 0;
248 
249 	if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
250 	    (key = data->phase2_method->getKey(sm, data->phase2_priv,
251 					       &key_len)) == NULL) {
252 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
253 			   "from Phase 2");
254 		return -1;
255 	}
256 
257 	if (key_len > isk_len)
258 		key_len = isk_len;
259 	os_memcpy(isk, key, key_len);
260 	os_free(key);
261 
262 	return 0;
263 }
264 
265 
266 static int
eap_peap_derive_cmk(struct eap_sm * sm,struct eap_peap_data * data)267 eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
268 {
269 	u8 *tk;
270 	u8 isk[32], imck[60];
271 
272 	/*
273 	 * Tunnel key (TK) is the first 60 octets of the key generated by
274 	 * phase 1 of PEAP (based on TLS).
275 	 */
276 	tk = data->key_data;
277 	if (tk == NULL)
278 		return -1;
279 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
280 
281 	if (data->reauth &&
282 	    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
283 		/* Fast-connect: IPMK|CMK = TK */
284 		os_memcpy(data->ipmk, tk, 40);
285 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
286 				data->ipmk, 40);
287 		os_memcpy(data->cmk, tk + 40, 20);
288 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
289 				data->cmk, 20);
290 		return 0;
291 	}
292 
293 	if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
294 		return -1;
295 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
296 
297 	/*
298 	 * IPMK Seed = "Inner Methods Compound Keys" | ISK
299 	 * TempKey = First 40 octets of TK
300 	 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
301 	 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
302 	 * in the end of the label just before ISK; is that just a typo?)
303 	 */
304 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
305 	if (peap_prfplus(data->peap_version, tk, 40,
306 			 "Inner Methods Compound Keys",
307 			 isk, sizeof(isk), imck, sizeof(imck)) < 0)
308 		return -1;
309 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
310 			imck, sizeof(imck));
311 
312 	os_memcpy(data->ipmk, imck, 40);
313 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
314 	os_memcpy(data->cmk, imck + 40, 20);
315 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
316 
317 	return 0;
318 }
319 
320 
321 static int
eap_tlv_add_cryptobinding(struct eap_sm * sm,struct eap_peap_data * data,struct wpabuf * buf)322 eap_tlv_add_cryptobinding(struct eap_sm *sm,
323 			  struct eap_peap_data *data,
324 			  struct wpabuf *buf)
325 {
326 	u8 *mac;
327 	u8 eap_type = EAP_TYPE_PEAP;
328 	const u8 *addr[2];
329 	size_t len[2];
330 	u16 tlv_type;
331 
332 	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
333 	addr[0] = wpabuf_put(buf, 0);
334 	len[0] = 60;
335 	addr[1] = &eap_type;
336 	len[1] = 1;
337 
338 	tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
339 	if (data->peap_version >= 2)
340 		tlv_type |= EAP_TLV_TYPE_MANDATORY;
341 	wpabuf_put_be16(buf, tlv_type);
342 	wpabuf_put_be16(buf, 56);
343 
344 	wpabuf_put_u8(buf, 0); /* Reserved */
345 	wpabuf_put_u8(buf, data->peap_version); /* Version */
346 	wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
347 	wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
348 	wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
349 	mac = wpabuf_put(buf, 20); /* Compound_MAC */
350 	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
351 	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
352 		    addr[0], len[0]);
353 	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
354 		    addr[1], len[1]);
355 	hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
356 	wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
357 	data->crypto_binding_used = 1;
358 
359 	return 0;
360 }
361 
362 
363 /**
364  * eap_tlv_build_result - Build EAP-TLV Result message
365  * @id: EAP identifier for the header
366  * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
367  * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
368  *
369  * This function builds an EAP-TLV Result message. The caller is responsible
370  * for freeing the returned buffer.
371  */
372 static struct wpabuf *
eap_tlv_build_result(struct eap_sm * sm,struct eap_peap_data * data,int crypto_tlv_used,int id,u16 status)373 eap_tlv_build_result(struct eap_sm *sm,
374 		     struct eap_peap_data *data,
375 		     int crypto_tlv_used,
376 		     int id, u16 status)
377 {
378 	struct wpabuf *msg;
379 	size_t len;
380 
381 	if (data->crypto_binding == NO_BINDING)
382 		crypto_tlv_used = 0;
383 
384 	len = 6;
385 	if (crypto_tlv_used)
386 		len += 60; /* Cryptobinding TLV */
387 	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
388 			    EAP_CODE_RESPONSE, id);
389 	if (msg == NULL)
390 		return NULL;
391 
392 	wpabuf_put_u8(msg, 0x80); /* Mandatory */
393 	wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
394 	wpabuf_put_be16(msg, 2); /* Length */
395 	wpabuf_put_be16(msg, status); /* Status */
396 
397 	if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
398 		wpabuf_free(msg);
399 		return NULL;
400 	}
401 
402 	return msg;
403 }
404 
405 
406 static int
eap_tlv_validate_cryptobinding(struct eap_sm * sm,struct eap_peap_data * data,const u8 * crypto_tlv,size_t crypto_tlv_len)407 eap_tlv_validate_cryptobinding(struct eap_sm *sm,
408 			       struct eap_peap_data *data,
409 			       const u8 *crypto_tlv,
410 			       size_t crypto_tlv_len)
411 {
412 	u8 buf[61], mac[SHA1_MAC_LEN];
413 	const u8 *pos;
414 
415 	if (eap_peap_derive_cmk(sm, data) < 0) {
416 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
417 		return -1;
418 	}
419 
420 	if (crypto_tlv_len != 4 + 56) {
421 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
422 			   "length %d", (int) crypto_tlv_len);
423 		return -1;
424 	}
425 
426 	pos = crypto_tlv;
427 	pos += 4; /* TLV header */
428 	if (pos[1] != data->peap_version) {
429 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
430 			   "mismatch (was %d; expected %d)",
431 			   pos[1], data->peap_version);
432 		return -1;
433 	}
434 
435 	if (pos[3] != 0) {
436 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
437 			   "SubType %d", pos[3]);
438 		return -1;
439 	}
440 	pos += 4;
441 	os_memcpy(data->binding_nonce, pos, 32);
442 	pos += 32; /* Nonce */
443 
444 	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
445 	os_memcpy(buf, crypto_tlv, 60);
446 	os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
447 	buf[60] = EAP_TYPE_PEAP;
448 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data",
449 		    buf, sizeof(buf));
450 	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
451 
452 	if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
453 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
454 			   "cryptobinding TLV");
455 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC",
456 			    pos, SHA1_MAC_LEN);
457 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC",
458 			    mac, SHA1_MAC_LEN);
459 		return -1;
460 	}
461 
462 	wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
463 
464 	return 0;
465 }
466 
peap_phase2_sufficient(struct eap_sm * sm,struct eap_peap_data * data)467 static bool peap_phase2_sufficient(struct eap_sm *sm,
468 				   struct eap_peap_data *data)
469 {
470 	if ((data->phase2_auth == ALWAYS ||
471 	     (data->phase2_auth == FOR_INITIAL &&
472 	      !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn) &&
473 	      !data->ssl.client_cert_conf) ||
474 	     data->phase2_eap_started) &&
475 	    !data->phase2_eap_success)
476 		return false;
477 	return true;
478 }
479 
480 
481 /**
482  * eap_tlv_process - Process a received EAP-TLV message and generate a response
483  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
484  * @ret: Return values from EAP request validation and processing
485  * @req: EAP-TLV request to be processed. The caller must have validated that
486  * the buffer is large enough to contain full request (hdr->length bytes) and
487  * that the EAP type is EAP_TYPE_TLV.
488  * @resp: Buffer to return a pointer to the allocated response message. This
489  * field should be initialized to %NULL before the call. The value will be
490  * updated if a response message is generated. The caller is responsible for
491  * freeing the allocated message.
492  * @force_failure: Force negotiation to fail
493  * Returns: 0 on success, -1 on failure
494  */
495 static int
eap_tlv_process(struct eap_sm * sm,struct eap_peap_data * data,struct eap_method_ret * ret,const struct wpabuf * req,struct wpabuf ** resp,int force_failure)496 eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
497 		struct eap_method_ret *ret,
498 		const struct wpabuf *req, struct wpabuf **resp,
499 		int force_failure)
500 {
501 	size_t left, tlv_len;
502 	const u8 *pos;
503 	const u8 *result_tlv = NULL, *crypto_tlv = NULL;
504 	size_t result_tlv_len = 0, crypto_tlv_len = 0;
505 	int tlv_type, mandatory;
506 
507 	/* Parse TLVs */
508 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
509 	if (pos == NULL)
510 		return -1;
511 	wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
512 	while (left >= 4) {
513 		mandatory = !!(pos[0] & 0x80);
514 		tlv_type = WPA_GET_BE16(pos) & 0x3fff;
515 		pos += 2;
516 		tlv_len = WPA_GET_BE16(pos);
517 		pos += 2;
518 		left -= 4;
519 		if (tlv_len > left) {
520 			wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
521 				   "(tlv_len=%lu left=%lu)",
522 				   (unsigned long) tlv_len,
523 				   (unsigned long) left);
524 			return -1;
525 		}
526 		switch (tlv_type) {
527 		case EAP_TLV_RESULT_TLV:
528 			result_tlv = pos;
529 			result_tlv_len = tlv_len;
530 			break;
531 		case EAP_TLV_CRYPTO_BINDING_TLV:
532 			crypto_tlv = pos;
533 			crypto_tlv_len = tlv_len;
534 			break;
535 		default:
536 			wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
537 				   "%d%s", tlv_type,
538 				   mandatory ? " (mandatory)" : "");
539 			if (mandatory) {
540 				/* NAK TLV and ignore all TLVs in this packet.
541 				 */
542 				*resp = eap_tlv_build_nak(eap_get_id(req),
543 							  tlv_type);
544 				return *resp == NULL ? -1 : 0;
545 			}
546 			/* Ignore this TLV, but process other TLVs */
547 			break;
548 		}
549 
550 		pos += tlv_len;
551 		left -= tlv_len;
552 	}
553 	if (left) {
554 		wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
555 			   "Request (left=%lu)", (unsigned long) left);
556 		return -1;
557 	}
558 
559 	/* Process supported TLVs */
560 	if (crypto_tlv && data->crypto_binding != NO_BINDING) {
561 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
562 			    crypto_tlv, crypto_tlv_len);
563 		if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
564 						   crypto_tlv_len + 4) < 0) {
565 			if (result_tlv == NULL)
566 				return -1;
567 			force_failure = 1;
568 			crypto_tlv = NULL; /* do not include Cryptobinding TLV
569 					    * in response, if the received
570 					    * cryptobinding was invalid. */
571 		}
572 	} else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
573 		wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
574 		return -1;
575 	}
576 
577 	if (result_tlv) {
578 		int status, resp_status;
579 		wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
580 			    result_tlv, result_tlv_len);
581 		if (result_tlv_len < 2) {
582 			wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
583 				   "(len=%lu)",
584 				   (unsigned long) result_tlv_len);
585 			return -1;
586 		}
587 		status = WPA_GET_BE16(result_tlv);
588 		if (status == EAP_TLV_RESULT_SUCCESS) {
589 			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
590 				   "- EAP-TLV/Phase2 Completed");
591 			if (force_failure) {
592 				wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
593 					   " - force failed Phase 2");
594 				resp_status = EAP_TLV_RESULT_FAILURE;
595 				ret->decision = DECISION_FAIL;
596 			} else if (!peap_phase2_sufficient(sm, data)) {
597 				wpa_printf(MSG_INFO,
598 					   "EAP-PEAP: Server indicated Phase 2 success, but sufficient Phase 2 authentication has not been completed");
599 				resp_status = EAP_TLV_RESULT_FAILURE;
600 				ret->decision = DECISION_FAIL;
601 			} else {
602 				resp_status = EAP_TLV_RESULT_SUCCESS;
603 				ret->decision = DECISION_UNCOND_SUCC;
604 			}
605 		} else if (status == EAP_TLV_RESULT_FAILURE) {
606 			wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
607 			resp_status = EAP_TLV_RESULT_FAILURE;
608 			ret->decision = DECISION_FAIL;
609 		} else {
610 			wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
611 				   "Status %d", status);
612 			resp_status = EAP_TLV_RESULT_FAILURE;
613 			ret->decision = DECISION_FAIL;
614 		}
615 		ret->methodState = METHOD_DONE;
616 
617 		*resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
618 					     eap_get_id(req), resp_status);
619 	}
620 
621 	return 0;
622 }
623 
624 
625 static struct wpabuf *
eap_peapv2_tlv_eap_payload(struct wpabuf * buf)626 eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
627 {
628 	struct wpabuf *e;
629 	struct eap_tlv_hdr *tlv;
630 
631 	if (buf == NULL)
632 		return NULL;
633 
634 	/* Encapsulate EAP packet in EAP-Payload TLV */
635 	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
636 	e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
637 	if (e == NULL) {
638 		wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
639 			   "for TLV encapsulation");
640 		wpabuf_free(buf);
641 		return NULL;
642 	}
643 	tlv = wpabuf_put(e, sizeof(*tlv));
644 	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
645 				     EAP_TLV_EAP_PAYLOAD_TLV);
646 	tlv->length = host_to_be16(wpabuf_len(buf));
647 	wpabuf_put_buf(e, buf);
648 	wpabuf_free(buf);
649 	return e;
650 }
651 
652 
eap_peap_phase2_request(struct eap_sm * sm,struct eap_peap_data * data,struct eap_method_ret * ret,struct wpabuf * req,struct wpabuf ** resp)653 static int eap_peap_phase2_request(struct eap_sm *sm,
654 			struct eap_peap_data *data,
655 			struct eap_method_ret *ret,
656 			struct wpabuf *req,
657 			struct wpabuf **resp)
658 {
659 	struct eap_hdr *hdr = wpabuf_mhead(req);
660 	size_t len = be_to_host16(hdr->length);
661 	u8 *pos;
662 	struct eap_method_ret iret;
663 
664 	if (len <= sizeof(struct eap_hdr)) {
665 		wpa_printf(MSG_INFO, "EAP-PEAP: too short "
666 			   "Phase 2 request (len=%lu)", (unsigned long) len);
667 		return -1;
668 	}
669 	pos = (u8 *) (hdr + 1);
670 	wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
671 	switch (*pos) {
672 	case EAP_TYPE_IDENTITY:
673 		*resp = eap_sm_build_identity_resp(sm, hdr->identifier, 1);
674 		break;
675 	case EAP_TYPE_TLV:
676 		os_memset(&iret, 0, sizeof(iret));
677 		if (eap_tlv_process(sm, data, &iret, req, resp,
678 				    data->phase2_eap_started &&
679 				    !data->phase2_eap_success)) {
680 			ret->methodState = METHOD_DONE;
681 			ret->decision = DECISION_FAIL;
682 			return -1;
683 		}
684 		if (iret.methodState == METHOD_DONE ||
685 		    iret.methodState == METHOD_MAY_CONT) {
686 			ret->methodState = iret.methodState;
687 			ret->decision = iret.decision;
688 			data->phase2_success = 1;
689 		}
690 		break;
691 	case EAP_TYPE_EXPANDED:
692 #ifdef EAP_TNC
693 		if (data->soh) {
694 			const u8 *epos;
695 			size_t eleft;
696 
697 			epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21,
698 						req, &eleft);
699 			if (epos) {
700 				struct wpabuf *buf;
701 				wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH EAP Extensions");
702 				buf = tncc_process_soh_request(data->soh,
703 							       epos, eleft);
704 				if (buf) {
705 					*resp = eap_msg_alloc(
706 						EAP_VENDOR_MICROSOFT, 0x21,
707 						wpabuf_len(buf),
708 						EAP_CODE_RESPONSE,
709 						hdr->identifier);
710 					if (*resp == NULL) {
711 						ret->methodState = METHOD_DONE;
712 						ret->decision = DECISION_FAIL;
713 						return -1;
714 					}
715 					wpabuf_put_buf(*resp, buf);
716 					wpabuf_free(buf);
717 					break;
718 				}
719 			}
720 		}
721 #endif /* EAP_TNC */
722 		/* fall through */
723 	default:
724 		if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
725 		    data->phase2_type.method == EAP_TYPE_NONE) {
726 			size_t i;
727 			for (i = 0; i < data->num_phase2_types; i++) {
728 				if (data->phase2_types[i].vendor !=
729 				    EAP_VENDOR_IETF ||
730 				    data->phase2_types[i].method != *pos)
731 					continue;
732 
733 				data->phase2_type.vendor =
734 					data->phase2_types[i].vendor;
735 				data->phase2_type.method =
736 					data->phase2_types[i].method;
737 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
738 					  "Phase 2 EAP vendor %d method %d",
739 					  data->phase2_type.vendor,
740 					  data->phase2_type.method);
741 				break;
742 			}
743 		}
744 		if (*pos != data->phase2_type.method ||
745 		    *pos == EAP_TYPE_NONE) {
746 			if (eap_peer_tls_phase2_nak(data->phase2_types,
747 						    data->num_phase2_types,
748 						    hdr, resp))
749 				return -1;
750 			return 0;
751 		}
752 
753 		if (data->phase2_priv == NULL) {
754 			data->phase2_method = eap_peer_get_eap_method(
755 				data->phase2_type.vendor,
756 				data->phase2_type.method);
757 			if (data->phase2_method) {
758 				sm->init_phase2 = 1;
759 				data->phase2_priv =
760 					data->phase2_method->init(sm);
761 				sm->init_phase2 = 0;
762 			}
763 		}
764 		if (data->phase2_priv == NULL || data->phase2_method == NULL) {
765 			wpa_printf(MSG_ERROR, "EAP-PEAP: failed to initialize "
766 				  "Phase 2 EAP method %d", *pos);
767 			ret->methodState = METHOD_DONE;
768 			ret->decision = DECISION_FAIL;
769 			return -1;
770 		}
771 		data->phase2_eap_started = 1;
772 		os_memset(&iret, 0, sizeof(iret));
773 		*resp = data->phase2_method->process(sm, data->phase2_priv,
774 						     &iret, req);
775 		if ((iret.methodState == METHOD_DONE ||
776 		     iret.methodState == METHOD_MAY_CONT) &&
777 		    (iret.decision == DECISION_UNCOND_SUCC ||
778 		     iret.decision == DECISION_COND_SUCC)) {
779 			data->phase2_eap_success = 1;
780 			data->phase2_success = 1;
781 		}
782 		break;
783 	}
784 
785 	if (*resp == NULL) {
786 		wpa_printf(MSG_ERROR, "phase 2 response failure");
787 		wpabuf_free(data->pending_phase2_req);
788 		data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
789 	}
790 /*
791     if (*resp == NULL &&
792 	    (config->pending_req_identity || config->pending_req_password ||
793 	     config->pending_req_otp || config->pending_req_new_password)) {
794 		wpabuf_free(data->pending_phase2_req);
795 		data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
796 	}
797 */
798 
799 	return 0;
800 }
801 
802 
803 static int
eap_peap_decrypt(struct eap_sm * sm,struct eap_peap_data * data,struct eap_method_ret * ret,const struct eap_hdr * req,const struct wpabuf * in_data,struct wpabuf ** out_data)804 eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
805 		 struct eap_method_ret *ret,
806 		 const struct eap_hdr *req,
807 		 const struct wpabuf *in_data,
808 		 struct wpabuf **out_data)
809 {
810 	struct wpabuf *in_decrypted = NULL;
811 	int res, skip_change = 0;
812 	struct eap_hdr *hdr, *rhdr;
813 	struct wpabuf *resp = NULL;
814 	size_t len;
815 
816 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
817 		  " Phase 2", (unsigned long) wpabuf_len(in_data));
818 
819 	if (data->pending_phase2_req) {
820 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
821 			   "skip decryption and use old data");
822 		/* Clear TLS reassembly state. */
823 		eap_peer_tls_reset_input(&data->ssl);
824 		in_decrypted = data->pending_phase2_req;
825 		data->pending_phase2_req = NULL;
826 		skip_change = 1;
827 		goto continue_req;
828 	}
829 
830 	if (wpabuf_len(in_data) == 0 && sm->workaround &&
831 	    data->phase2_success) {
832 		/*
833 		 * Cisco ACS seems to be using TLS ACK to terminate
834 		 * EAP-PEAPv0/GTC. Try to reply with TLS ACK.
835 		 */
836 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
837 			   "expected data - acknowledge with TLS ACK since "
838 			   "Phase 2 has been completed");
839 		ret->decision = DECISION_COND_SUCC;
840 		ret->methodState = METHOD_DONE;
841 		return 1;
842 	} else if (wpabuf_len(in_data) == 0) {
843 		/* Received TLS ACK - requesting more fragments */
844 		return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
845 					    data->peap_version,
846 					    req->identifier, NULL, out_data);
847 	}
848 
849 	res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
850 	if (res)
851 		return res;
852 
853 continue_req:
854 	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
855 			in_decrypted);
856 
857 	hdr = wpabuf_mhead(in_decrypted);
858 	if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST &&
859 	    be_to_host16(hdr->length) == 5 &&
860 	    eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) {
861 		/* At least FreeRADIUS seems to send full EAP header with
862 		 * EAP Request Identity */
863 		skip_change = 1;
864 	}
865 	if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST &&
866 	    eap_get_type(in_decrypted) == EAP_TYPE_TLV) {
867 		skip_change = 1;
868 	}
869 
870 	if (data->peap_version == 0 && !skip_change) {
871 		struct eap_hdr *nhdr;
872 		struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
873 						   wpabuf_len(in_decrypted));
874 		if (nmsg == NULL) {
875 			wpabuf_free(in_decrypted);
876 			return 0;
877 		}
878 		nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
879 		wpabuf_put_buf(nmsg, in_decrypted);
880 		nhdr->code = req->code;
881 		nhdr->identifier = req->identifier;
882 		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
883 					    wpabuf_len(in_decrypted));
884 
885 		wpabuf_free(in_decrypted);
886 		in_decrypted = nmsg;
887 	}
888 
889 	if (data->peap_version >= 2) {
890 		struct eap_tlv_hdr *tlv;
891 		struct wpabuf *nmsg;
892 
893 		if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
894 			wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
895 				   "EAP TLV");
896 			wpabuf_free(in_decrypted);
897 			return 0;
898 		}
899 		tlv = wpabuf_mhead(in_decrypted);
900 		if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
901 		    EAP_TLV_EAP_PAYLOAD_TLV) {
902 			wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
903 			wpabuf_free(in_decrypted);
904 			return 0;
905 		}
906 		if (sizeof(*tlv) + be_to_host16(tlv->length) >
907 		    wpabuf_len(in_decrypted)) {
908 			wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
909 				   "length");
910 			wpabuf_free(in_decrypted);
911 			return 0;
912 		}
913 		hdr = (struct eap_hdr *) (tlv + 1);
914 		if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
915 			wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
916 				   "EAP packet in EAP TLV");
917 			wpabuf_free(in_decrypted);
918 			return 0;
919 		}
920 
921 		nmsg = wpabuf_alloc(be_to_host16(hdr->length));
922 		if (nmsg == NULL) {
923 			wpabuf_free(in_decrypted);
924 			return 0;
925 		}
926 
927 		wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
928 		wpabuf_free(in_decrypted);
929 		in_decrypted = nmsg;
930 	}
931 
932 	hdr = wpabuf_mhead(in_decrypted);
933 	if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
934 		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
935 			   "EAP frame (len=%lu)",
936 			   (unsigned long) wpabuf_len(in_decrypted));
937 		wpabuf_free(in_decrypted);
938 		return 0;
939 	}
940 	len = be_to_host16(hdr->length);
941 	if (len > wpabuf_len(in_decrypted)) {
942 		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
943 			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
944 			   (unsigned long) wpabuf_len(in_decrypted),
945 			   (unsigned long) len);
946 		wpabuf_free(in_decrypted);
947 		return 0;
948 	}
949 	if (len < wpabuf_len(in_decrypted)) {
950 		wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
951 			   "shorter length than full decrypted data "
952 			   "(%lu < %lu)",
953 			   (unsigned long) len,
954 			   (unsigned long) wpabuf_len(in_decrypted));
955 	}
956 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
957 		  "identifier=%d length=%lu\n", hdr->code, hdr->identifier,
958 		  (unsigned long) len);
959 	switch (hdr->code) {
960 	case EAP_CODE_REQUEST:
961 		if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
962 					    &resp)) {
963 			wpabuf_free(in_decrypted);
964 			wpa_printf(MSG_ERROR, "EAP-PEAP: Phase2 Request "
965 				  "processing failed");
966 			return 0;
967 		}
968 		break;
969 	case EAP_CODE_SUCCESS:
970 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
971 		if (data->peap_version == 1) {
972 			/* EAP-Success within TLS tunnel is used to indicate
973 			 * shutdown of the TLS channel. The authentication has
974 			 * been completed. */
975 			if (!peap_phase2_sufficient(sm, data)) {
976 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
977 					   "Success used to indicate success, "
978 					   "but Phase 2 EAP was not yet "
979 					   "completed successfully");
980 				ret->methodState = METHOD_DONE;
981 				ret->decision = DECISION_FAIL;
982 				wpabuf_free(in_decrypted);
983 				return 0;
984 			}
985 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
986 				   "EAP-Success within TLS tunnel - "
987 				   "authentication completed");
988 			ret->decision = DECISION_UNCOND_SUCC;
989 			ret->methodState = METHOD_DONE;
990 			data->phase2_success = 1;
991 			if (data->peap_outer_success == 2) {
992 				wpabuf_free(in_decrypted);
993 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
994 					   "to finish authentication");
995 				return 1;
996 			} else if (data->peap_outer_success == 1) {
997 				/* Reply with EAP-Success within the TLS
998 				 * channel to complete the authentication. */
999 				resp = wpabuf_alloc(sizeof(struct eap_hdr));
1000 				if (resp) {
1001 					rhdr = wpabuf_put(resp, sizeof(*rhdr));
1002 					rhdr->code = EAP_CODE_SUCCESS;
1003 					rhdr->identifier = hdr->identifier;
1004 					rhdr->length =
1005 						host_to_be16(sizeof(*rhdr));
1006 				}
1007 			} else {
1008 				/* No EAP-Success expected for Phase 1 (outer,
1009 				 * unencrypted auth), so force EAP state
1010 				 * machine to SUCCESS state. */
1011 				sm->peap_done = TRUE;
1012 			}
1013 		} else {
1014 			/* FIX: ? */
1015 		}
1016 		break;
1017 	case EAP_CODE_FAILURE:
1018 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1019 		ret->decision = DECISION_FAIL;
1020 		ret->methodState = METHOD_MAY_CONT;
1021 		ret->allowNotifications = FALSE;
1022 		/* Reply with EAP-Failure within the TLS channel to complete
1023 		 * failure reporting. */
1024 		resp = wpabuf_alloc(sizeof(struct eap_hdr));
1025 		if (resp) {
1026 			rhdr = wpabuf_put(resp, sizeof(*rhdr));
1027 			rhdr->code = EAP_CODE_FAILURE;
1028 			rhdr->identifier = hdr->identifier;
1029 			rhdr->length = host_to_be16(sizeof(*rhdr));
1030 		}
1031 		break;
1032 	default:
1033 		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1034 			   "Phase 2 EAP header", hdr->code);
1035 		break;
1036 	}
1037 
1038 	wpabuf_free(in_decrypted);
1039 
1040 	if (resp) {
1041 		int skip_change2 = 0;
1042 		struct wpabuf *rmsg, buf;
1043 
1044 		wpa_hexdump_buf_key(MSG_DEBUG,
1045 				    "EAP-PEAP: Encrypting Phase 2 data", resp);
1046 		/* PEAP version changes */
1047 		if (data->peap_version >= 2) {
1048 			resp = eap_peapv2_tlv_eap_payload(resp);
1049 			if (resp == NULL)
1050 				return -1;
1051 		}
1052 		if (wpabuf_len(resp) >= 5 &&
1053 		    wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
1054 		    eap_get_type(resp) == EAP_TYPE_TLV)
1055 			skip_change2 = 1;
1056 		rmsg = resp;
1057 		if (data->peap_version == 0 && !skip_change2) {
1058 			wpabuf_set(&buf, wpabuf_head_u8(resp) +
1059 				   sizeof(struct eap_hdr),
1060 				   wpabuf_len(resp) - sizeof(struct eap_hdr));
1061 			rmsg = &buf;
1062 		}
1063 
1064 		if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
1065 					 data->peap_version, req->identifier,
1066 					 rmsg, out_data)) {
1067 			wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
1068 				   "a Phase 2 frame");
1069 		}
1070 		wpabuf_free(resp);
1071 	}
1072 
1073 	return 0;
1074 }
1075 
1076 
eap_peap_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)1077 static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
1078 					struct eap_method_ret *ret,
1079 					const struct wpabuf *reqData)
1080 {
1081 	const struct eap_hdr *req;
1082 	size_t left;
1083 	int res;
1084 	u8 flags, id;
1085 	struct wpabuf *resp;
1086 	const u8 *pos;
1087 	struct eap_peap_data *data = priv;
1088 
1089 	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
1090 					reqData, &left, &flags);
1091 	if (pos == NULL)
1092 		return NULL;
1093 	req = wpabuf_head(reqData);
1094 	id = req->identifier;
1095 
1096 	if (flags & EAP_TLS_FLAGS_START) {
1097 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
1098 			   "ver=%d)", flags & EAP_TLS_VERSION_MASK,
1099 			data->peap_version);
1100 		if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version)
1101 			data->peap_version = flags & EAP_TLS_VERSION_MASK;
1102 		if (data->force_peap_version >= 0 &&
1103 		    data->force_peap_version != data->peap_version) {
1104 			wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
1105 				   "forced PEAP version %d",
1106 				   data->force_peap_version);
1107 			ret->methodState = METHOD_DONE;
1108 			ret->decision = DECISION_FAIL;
1109 			ret->allowNotifications = FALSE;
1110 			return NULL;
1111 		}
1112 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
1113 			   data->peap_version);
1114 		left = 0; /* make sure that this frame is empty, even though it
1115 			   * should always be, anyway */
1116 	}
1117 
1118 	resp = NULL;
1119 	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1120 	    !data->resuming) {
1121 		struct wpabuf msg;
1122 		wpabuf_set(&msg, pos, left);
1123 		res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
1124 	} else {
1125 		res = eap_peer_tls_process_helper(sm, &data->ssl,
1126 						  EAP_TYPE_PEAP,
1127 						  data->peap_version, id, pos,
1128 						  left, &resp);
1129 
1130 		if (res < 0) {
1131 			wpa_printf(MSG_DEBUG,
1132 				   "EAP-PEAP: TLS processing failed");
1133 			ret->methodState = METHOD_DONE;
1134 			ret->decision = DECISION_FAIL;
1135 			return resp;
1136 		}
1137 
1138 		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1139 			char label[24] = {0};
1140 			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2");
1141 			os_free(data->key_data);
1142 			/* draft-josefsson-ppext-eap-tls-eap-05.txt
1143 			 * specifies that PEAPv1 would use "client PEAP
1144 			 * encryption" as the label. However, most existing
1145 			 * PEAPv1 implementations seem to be using the old
1146 			 * label, "client EAP encryption", instead. Use the old
1147 			 * label by default, but allow it to be configured with
1148 			 * phase1 parameter peaplabel=1. */
1149 			if (data->peap_version > 1 || data->force_new_label)
1150 				os_strlcpy(label, "client PEAP encryption", 24);
1151 			else
1152 				os_strlcpy(label, "client EAP encryption", 24);
1153 			wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
1154 				   "key derivation", label);
1155 			data->key_data =
1156 				eap_peer_tls_derive_key(sm, &data->ssl, label,
1157 							EAP_TLS_KEY_LEN);
1158 			if (data->key_data) {
1159 				wpa_hexdump_key(MSG_DEBUG,
1160 						"EAP-PEAP: Derived key",
1161 						data->key_data,
1162 						EAP_TLS_KEY_LEN);
1163 			} else {
1164 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
1165 					   "derive key");
1166 			}
1167 
1168 			os_free(data->session_id);
1169 			data->session_id =
1170 				eap_peer_tls_derive_session_id(sm, &data->ssl,
1171 							       EAP_TYPE_PEAP,
1172 							       &data->id_len);
1173 			if (data->session_id) {
1174 				wpa_hexdump(MSG_DEBUG,
1175 					    "EAP-PEAP: Derived Session-Id",
1176 					    data->session_id, data->id_len);
1177 			} else {
1178 				wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to "
1179 					   "derive Session-Id");
1180 			}
1181 
1182 			if (sm->workaround && data->resuming) {
1183 				/*
1184 				 * At least few RADIUS servers (Aegis v1.1.6;
1185 				 * but not v1.1.4; and Cisco ACS) seem to be
1186 				 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco
1187 				 * ACS) session resumption with outer
1188 				 * EAP-Success. This does not seem to follow
1189 				 * draft-josefsson-pppext-eap-tls-eap-05.txt
1190 				 * section 4.2, so only allow this if EAP
1191 				 * workarounds are enabled.
1192 				 */
1193 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
1194 					   "allow outer EAP-Success to "
1195 					   "terminate PEAP resumption");
1196 				ret->decision = DECISION_COND_SUCC;
1197 				data->phase2_success = 1;
1198 			}
1199 
1200 			data->resuming = 0;
1201 		}
1202 
1203 		if (res == 2) {
1204 			struct wpabuf msg;
1205 			/*
1206 			 * Application data included in the handshake message.
1207 			 */
1208 			wpabuf_free(data->pending_phase2_req);
1209 			data->pending_phase2_req = resp;
1210 			resp = NULL;
1211 			wpabuf_set(&msg, pos, left);
1212 			res = eap_peap_decrypt(sm, data, ret, req, &msg,
1213 					       &resp);
1214 		}
1215 	}
1216 
1217 	if (ret->methodState == METHOD_DONE) {
1218 		ret->allowNotifications = FALSE;
1219 	}
1220 
1221 	if (res == 1) {
1222 		wpabuf_free(resp);
1223 		return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
1224 					      data->peap_version);
1225 	}
1226 
1227 	return resp;
1228 }
1229 
1230 
1231 static bool
eap_peap_has_reauth_data(struct eap_sm * sm,void * priv)1232 eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
1233 {
1234 	struct eap_peap_data *data = priv;
1235 
1236 	return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1237 		data->phase2_success && data->phase2_auth != ALWAYS;
1238 }
1239 
1240 
1241 static void
eap_peap_deinit_for_reauth(struct eap_sm * sm,void * priv)1242 eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
1243 {
1244 	struct eap_peap_data *data = priv;
1245 	wpabuf_free(data->pending_phase2_req);
1246 	data->pending_phase2_req = NULL;
1247 	data->crypto_binding_used = 0;
1248 }
1249 
1250 
1251 static void *
eap_peap_init_for_reauth(struct eap_sm * sm,void * priv)1252 eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
1253 {
1254 	struct eap_peap_data *data = priv;
1255 	os_free(data->key_data);
1256 	data->key_data = NULL;
1257 	os_free(data->session_id);
1258 	data->session_id = NULL;
1259 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1260 		os_free(data);
1261 		return NULL;
1262 	}
1263 	if (data->phase2_priv && data->phase2_method &&
1264 	    data->phase2_method->init_for_reauth)
1265 		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1266 	data->phase2_success = 0;
1267 	data->phase2_eap_success = 0;
1268 	data->phase2_eap_started = 0;
1269 	data->resuming = 1;
1270 	data->reauth = 1;
1271 	sm->peap_done = FALSE;
1272 	return priv;
1273 }
1274 
1275 
1276 static int
eap_peap_get_status(struct eap_sm * sm,void * priv,char * buf,size_t buflen,int verbose)1277 eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
1278 		    size_t buflen, int verbose)
1279 {
1280 	struct eap_peap_data *data = priv;
1281 	int len, ret;
1282 
1283 	len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1284 	if (data->phase2_method) {
1285 		ret = snprintf(buf + len, buflen - len,
1286 				  "EAP-PEAPv%d Phase2 method=%d\n",
1287 				  data->peap_version,
1288 				  data->phase2_method->method);
1289 		if (ret < 0 || (size_t) ret >= buflen - len)
1290 			return len;
1291 		len += ret;
1292 	}
1293 	return len;
1294 }
1295 
1296 
1297 static bool
eap_peap_isKeyAvailable(struct eap_sm * sm,void * priv)1298 eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
1299 {
1300 	struct eap_peap_data *data = priv;
1301 	return data->key_data != NULL && data->phase2_success;
1302 }
1303 
1304 
1305 static u8 *
eap_peap_getKey(struct eap_sm * sm,void * priv,size_t * len)1306 eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1307 {
1308 	struct eap_peap_data *data = priv;
1309 	u8 *key;
1310 
1311 	if (data->key_data == NULL || !data->phase2_success)
1312 		return NULL;
1313 
1314 	key = os_malloc(EAP_TLS_KEY_LEN);
1315 	if (key == NULL)
1316 		return NULL;
1317 
1318 	*len = EAP_TLS_KEY_LEN;
1319 
1320 	if (data->crypto_binding_used) {
1321 		u8 csk[128];
1322 		/*
1323 		 * Note: It looks like Microsoft implementation requires null
1324 		 * termination for this label while the one used for deriving
1325 		 * IPMK|CMK did not use null termination.
1326 		 */
1327 		if (peap_prfplus(data->peap_version, data->ipmk, 40,
1328 				 "Session Key Generating Function",
1329 				 (u8 *) "\00", 1, csk, sizeof(csk)) < 0) {
1330 			os_free(key);
1331 			return NULL;
1332 		}
1333 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1334 		os_memcpy(key, csk, EAP_TLS_KEY_LEN);
1335 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1336 			    key, EAP_TLS_KEY_LEN);
1337 	} else
1338 		os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1339 
1340 	return key;
1341 }
1342 
1343 
1344 static u8 *
eap_peap_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1345 eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1346 {
1347 	struct eap_peap_data *data = priv;
1348 	u8 *id;
1349 
1350 	if (data->session_id == NULL || !data->phase2_success)
1351 		return NULL;
1352 
1353 	id = os_malloc(data->id_len);
1354 	if (id == NULL)
1355 		return NULL;
1356 
1357 	*len = data->id_len;
1358 	os_memcpy(id, data->session_id, data->id_len);
1359 
1360 	return id;
1361 }
1362 
1363 
1364 int
eap_peer_peap_register(void)1365 eap_peer_peap_register(void)
1366 {
1367 	struct eap_method *eap;
1368 	int ret;
1369 
1370 	eap = eap_peer_method_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP,
1371 				    "PEAP");
1372 	if (eap == NULL)
1373 		return -1;
1374 
1375 	eap->init = eap_peap_init;
1376 	eap->deinit = eap_peap_deinit;
1377 	eap->process = eap_peap_process;
1378 	eap->isKeyAvailable = eap_peap_isKeyAvailable;
1379 	eap->getKey = eap_peap_getKey;
1380 	eap->get_status = eap_peap_get_status;
1381 	eap->has_reauth_data = eap_peap_has_reauth_data;
1382 	eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
1383 	eap->init_for_reauth = eap_peap_init_for_reauth;
1384 	eap->getSessionId = eap_peap_get_session_id;
1385 
1386 	ret = eap_peer_method_register(eap);
1387 	if (ret)
1388 		eap_peer_method_free(eap);
1389 	return ret;
1390 }
1391 
1392 #endif /* EAP_PEAP */
1393