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