xref: /freebsd/contrib/wpa/src/eap_server/eap_server_peap.c (revision d5b0e70f7e04d971691517ce1304d86a1e367e2e)
1 /*
2  * hostapd / 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 "crypto/random.h"
15 #include "eap_i.h"
16 #include "eap_tls_common.h"
17 #include "eap_common/eap_tlv_common.h"
18 #include "eap_common/eap_peap_common.h"
19 #include "tncs.h"
20 
21 
22 /* Maximum supported PEAP version
23  * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
24  * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
25  */
26 #define EAP_PEAP_VERSION 1
27 
28 
29 static void eap_peap_reset(struct eap_sm *sm, void *priv);
30 
31 
32 struct eap_peap_data {
33 	struct eap_ssl_data ssl;
34 	enum {
35 		START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
36 		PHASE2_METHOD, PHASE2_SOH,
37 		PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
38 	} state;
39 
40 	int peap_version;
41 	int recv_version;
42 	const struct eap_method *phase2_method;
43 	void *phase2_priv;
44 	int force_version;
45 	struct wpabuf *pending_phase2_resp;
46 	enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
47 	int crypto_binding_sent;
48 	int crypto_binding_used;
49 	enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
50 	u8 binding_nonce[32];
51 	u8 ipmk[40];
52 	u8 cmk[20];
53 	u8 *phase2_key;
54 	size_t phase2_key_len;
55 	struct wpabuf *soh_response;
56 };
57 
58 
59 static const char * eap_peap_state_txt(int state)
60 {
61 	switch (state) {
62 	case START:
63 		return "START";
64 	case PHASE1:
65 		return "PHASE1";
66 	case PHASE1_ID2:
67 		return "PHASE1_ID2";
68 	case PHASE2_START:
69 		return "PHASE2_START";
70 	case PHASE2_ID:
71 		return "PHASE2_ID";
72 	case PHASE2_METHOD:
73 		return "PHASE2_METHOD";
74 	case PHASE2_SOH:
75 		return "PHASE2_SOH";
76 	case PHASE2_TLV:
77 		return "PHASE2_TLV";
78 	case SUCCESS_REQ:
79 		return "SUCCESS_REQ";
80 	case FAILURE_REQ:
81 		return "FAILURE_REQ";
82 	case SUCCESS:
83 		return "SUCCESS";
84 	case FAILURE:
85 		return "FAILURE";
86 	default:
87 		return "Unknown?!";
88 	}
89 }
90 
91 
92 static void eap_peap_state(struct eap_peap_data *data, int state)
93 {
94 	wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
95 		   eap_peap_state_txt(data->state),
96 		   eap_peap_state_txt(state));
97 	data->state = state;
98 	if (state == FAILURE || state == FAILURE_REQ)
99 		tls_connection_remove_session(data->ssl.conn);
100 }
101 
102 
103 static void eap_peap_valid_session(struct eap_sm *sm,
104 				   struct eap_peap_data *data)
105 {
106 	struct wpabuf *buf;
107 
108 	if (!sm->cfg->tls_session_lifetime ||
109 	    tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
110 		return;
111 
112 	buf = wpabuf_alloc(1 + 1 + sm->identity_len);
113 	if (!buf)
114 		return;
115 	wpabuf_put_u8(buf, EAP_TYPE_PEAP);
116 	if (sm->identity) {
117 		u8 id_len;
118 
119 		if (sm->identity_len <= 255)
120 			id_len = sm->identity_len;
121 		else
122 			id_len = 255;
123 		wpabuf_put_u8(buf, id_len);
124 		wpabuf_put_data(buf, sm->identity, id_len);
125 	} else {
126 		wpabuf_put_u8(buf, 0);
127 	}
128 	tls_connection_set_success_data(data->ssl.conn, buf);
129 }
130 
131 
132 static void eap_peap_req_success(struct eap_sm *sm,
133 				 struct eap_peap_data *data)
134 {
135 	if (data->state == FAILURE || data->state == FAILURE_REQ) {
136 		eap_peap_state(data, FAILURE);
137 		return;
138 	}
139 
140 	if (data->peap_version == 0) {
141 		data->tlv_request = TLV_REQ_SUCCESS;
142 		eap_peap_state(data, PHASE2_TLV);
143 	} else {
144 		eap_peap_state(data, SUCCESS_REQ);
145 	}
146 }
147 
148 
149 static void eap_peap_req_failure(struct eap_sm *sm,
150 				 struct eap_peap_data *data)
151 {
152 	if (data->state == FAILURE || data->state == FAILURE_REQ ||
153 	    data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) {
154 		eap_peap_state(data, FAILURE);
155 		return;
156 	}
157 
158 	if (data->peap_version == 0) {
159 		data->tlv_request = TLV_REQ_FAILURE;
160 		eap_peap_state(data, PHASE2_TLV);
161 	} else {
162 		eap_peap_state(data, FAILURE_REQ);
163 	}
164 }
165 
166 
167 static void * eap_peap_init(struct eap_sm *sm)
168 {
169 	struct eap_peap_data *data;
170 
171 	data = os_zalloc(sizeof(*data));
172 	if (data == NULL)
173 		return NULL;
174 	data->peap_version = EAP_PEAP_VERSION;
175 	data->force_version = -1;
176 	if (sm->user && sm->user->force_version >= 0) {
177 		data->force_version = sm->user->force_version;
178 		wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
179 			   data->force_version);
180 		data->peap_version = data->force_version;
181 	}
182 	data->state = START;
183 	data->crypto_binding = OPTIONAL_BINDING;
184 
185 	if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_PEAP)) {
186 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
187 		eap_peap_reset(sm, data);
188 		return NULL;
189 	}
190 
191 	return data;
192 }
193 
194 
195 static void eap_peap_reset(struct eap_sm *sm, void *priv)
196 {
197 	struct eap_peap_data *data = priv;
198 	if (data == NULL)
199 		return;
200 	if (data->phase2_priv && data->phase2_method)
201 		data->phase2_method->reset(sm, data->phase2_priv);
202 	eap_server_tls_ssl_deinit(sm, &data->ssl);
203 	wpabuf_free(data->pending_phase2_resp);
204 	os_free(data->phase2_key);
205 	wpabuf_free(data->soh_response);
206 	bin_clear_free(data, sizeof(*data));
207 }
208 
209 
210 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
211 					    struct eap_peap_data *data, u8 id)
212 {
213 	struct wpabuf *req;
214 
215 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
216 			    EAP_CODE_REQUEST, id);
217 	if (req == NULL) {
218 		wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
219 			   " request");
220 		eap_peap_state(data, FAILURE);
221 		return NULL;
222 	}
223 
224 	wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
225 
226 	eap_peap_state(data, PHASE1);
227 
228 	return req;
229 }
230 
231 
232 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
233 						 struct eap_peap_data *data,
234 						 u8 id)
235 {
236 	struct wpabuf *buf, *encr_req, msgbuf;
237 	const u8 *req;
238 	size_t req_len;
239 
240 	if (data->phase2_method == NULL || data->phase2_priv == NULL) {
241 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready");
242 		return NULL;
243 	}
244 	buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
245 	if (buf == NULL)
246 		return NULL;
247 
248 	req = wpabuf_head(buf);
249 	req_len = wpabuf_len(buf);
250 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
251 			req, req_len);
252 
253 	if (data->peap_version == 0 &&
254 	    data->phase2_method->method != EAP_TYPE_TLV) {
255 		req += sizeof(struct eap_hdr);
256 		req_len -= sizeof(struct eap_hdr);
257 	}
258 
259 	wpabuf_set(&msgbuf, req, req_len);
260 	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
261 	wpabuf_free(buf);
262 
263 	return encr_req;
264 }
265 
266 
267 #ifdef EAP_SERVER_TNC
268 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
269 						 struct eap_peap_data *data,
270 						 u8 id)
271 {
272 	struct wpabuf *buf1, *buf, *encr_req, msgbuf;
273 	const u8 *req;
274 	size_t req_len;
275 
276 	buf1 = tncs_build_soh_request();
277 	if (buf1 == NULL)
278 		return NULL;
279 
280 	buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
281 			    EAP_CODE_REQUEST, id);
282 	if (buf == NULL) {
283 		wpabuf_free(buf1);
284 		return NULL;
285 	}
286 	wpabuf_put_buf(buf, buf1);
287 	wpabuf_free(buf1);
288 
289 	req = wpabuf_head(buf);
290 	req_len = wpabuf_len(buf);
291 
292 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
293 			req, req_len);
294 
295 	req += sizeof(struct eap_hdr);
296 	req_len -= sizeof(struct eap_hdr);
297 	wpabuf_set(&msgbuf, req, req_len);
298 
299 	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
300 	wpabuf_free(buf);
301 
302 	return encr_req;
303 }
304 #endif /* EAP_SERVER_TNC */
305 
306 
307 static void eap_peap_get_isk(struct eap_peap_data *data,
308 			     u8 *isk, size_t isk_len)
309 {
310 	size_t key_len;
311 
312 	os_memset(isk, 0, isk_len);
313 	if (data->phase2_key == NULL)
314 		return;
315 
316 	key_len = data->phase2_key_len;
317 	if (key_len > isk_len)
318 		key_len = isk_len;
319 	os_memcpy(isk, data->phase2_key, key_len);
320 }
321 
322 
323 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
324 {
325 	u8 *tk;
326 	u8 isk[32], imck[60];
327 	int res;
328 	const char *label;
329 	const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
330 	const u8 *context = NULL;
331 	size_t context_len = 0;
332 
333 	if (data->ssl.tls_v13) {
334 		label = "EXPORTER_EAP_TLS_Key_Material";
335 		context = eap_tls13_context;
336 		context_len = sizeof(eap_tls13_context);
337 	} else {
338 		/* TODO: PEAPv1 - different label in some cases */
339 		label = "client EAP encryption";
340 	}
341 
342 	/*
343 	 * Tunnel key (TK) is the first 60 octets of the key generated by
344 	 * phase 1 of PEAP (based on TLS).
345 	 */
346 	tk = eap_server_tls_derive_key(sm, &data->ssl, label,
347 				       context, context_len,
348 				       EAP_TLS_KEY_LEN);
349 	if (tk == NULL)
350 		return -1;
351 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
352 
353 	if (tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn)) {
354 		/* Fast-connect: IPMK|CMK = TK */
355 		os_memcpy(data->ipmk, tk, 40);
356 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
357 				data->ipmk, 40);
358 		os_memcpy(data->cmk, tk + 40, 20);
359 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
360 				data->cmk, 20);
361 		os_free(tk);
362 		return 0;
363 	}
364 
365 	eap_peap_get_isk(data, isk, sizeof(isk));
366 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
367 
368 	/*
369 	 * IPMK Seed = "Inner Methods Compound Keys" | ISK
370 	 * TempKey = First 40 octets of TK
371 	 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
372 	 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
373 	 * in the end of the label just before ISK; is that just a typo?)
374 	 */
375 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
376 	res = peap_prfplus(data->peap_version, tk, 40,
377 			   "Inner Methods Compound Keys",
378 			   isk, sizeof(isk), imck, sizeof(imck));
379 	forced_memzero(isk, sizeof(isk));
380 	if (res < 0) {
381 		os_free(tk);
382 		return -1;
383 	}
384 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
385 			imck, sizeof(imck));
386 
387 	os_free(tk);
388 
389 	os_memcpy(data->ipmk, imck, 40);
390 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
391 	os_memcpy(data->cmk, imck + 40, 20);
392 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
393 	forced_memzero(imck, sizeof(imck));
394 
395 	return 0;
396 }
397 
398 
399 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
400 						 struct eap_peap_data *data,
401 						 u8 id)
402 {
403 	struct wpabuf *buf, *encr_req;
404 	size_t mlen;
405 
406 	mlen = 6; /* Result TLV */
407 	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
408 	    data->crypto_binding != NO_BINDING) {
409 		mlen += 60; /* Cryptobinding TLV */
410 #ifdef EAP_SERVER_TNC
411 		if (data->soh_response)
412 			mlen += wpabuf_len(data->soh_response);
413 #endif /* EAP_SERVER_TNC */
414 	}
415 
416 	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen,
417 			    EAP_CODE_REQUEST, id);
418 	if (buf == NULL)
419 		return NULL;
420 
421 	wpabuf_put_u8(buf, 0x80); /* Mandatory */
422 	wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
423 	/* Length */
424 	wpabuf_put_be16(buf, 2);
425 	/* Status */
426 	wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
427 			EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
428 
429 	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
430 	    data->crypto_binding != NO_BINDING) {
431 		u8 *mac;
432 		u8 eap_type = EAP_TYPE_PEAP;
433 		const u8 *addr[2];
434 		size_t len[2];
435 		u16 tlv_type;
436 
437 #ifdef EAP_SERVER_TNC
438 		if (data->soh_response) {
439 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
440 				   "Response TLV");
441 			wpabuf_put_buf(buf, data->soh_response);
442 			wpabuf_free(data->soh_response);
443 			data->soh_response = NULL;
444 		}
445 #endif /* EAP_SERVER_TNC */
446 
447 		if (eap_peap_derive_cmk(sm, data) < 0 ||
448 		    random_get_bytes(data->binding_nonce, 32)) {
449 			wpabuf_free(buf);
450 			return NULL;
451 		}
452 
453 		/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
454 		addr[0] = wpabuf_put(buf, 0);
455 		len[0] = 60;
456 		addr[1] = &eap_type;
457 		len[1] = 1;
458 
459 		tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
460 		wpabuf_put_be16(buf, tlv_type);
461 		wpabuf_put_be16(buf, 56);
462 
463 		wpabuf_put_u8(buf, 0); /* Reserved */
464 		wpabuf_put_u8(buf, data->peap_version); /* Version */
465 		wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
466 		wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
467 		wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
468 		mac = wpabuf_put(buf, 20); /* Compound_MAC */
469 		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
470 			    data->cmk, 20);
471 		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
472 			    addr[0], len[0]);
473 		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
474 			    addr[1], len[1]);
475 		hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
476 		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
477 			    mac, SHA1_MAC_LEN);
478 		data->crypto_binding_sent = 1;
479 	}
480 
481 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
482 			    buf);
483 
484 	encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
485 	wpabuf_free(buf);
486 
487 	return encr_req;
488 }
489 
490 
491 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
492 						  struct eap_peap_data *data,
493 						  u8 id, int success)
494 {
495 	struct wpabuf *encr_req, msgbuf;
496 	size_t req_len;
497 	struct eap_hdr *hdr;
498 
499 	req_len = sizeof(*hdr);
500 	hdr = os_zalloc(req_len);
501 	if (hdr == NULL)
502 		return NULL;
503 
504 	hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
505 	hdr->identifier = id;
506 	hdr->length = host_to_be16(req_len);
507 
508 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
509 			(u8 *) hdr, req_len);
510 
511 	wpabuf_set(&msgbuf, hdr, req_len);
512 	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
513 	os_free(hdr);
514 
515 	if (!data->ssl.tls_v13 ||
516 	    !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn)) {
517 		wpabuf_free(data->ssl.tls_out);
518 		data->ssl.tls_out_pos = 0;
519 		return encr_req;
520 	}
521 
522 	if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr_req)) < 0) {
523 		wpa_printf(MSG_INFO,
524 			   "EAP-PEAP: Failed to resize output buffer");
525 		wpabuf_free(encr_req);
526 		return NULL;
527 	}
528 	wpabuf_put_buf(data->ssl.tls_out, encr_req);
529 	wpa_hexdump_buf(MSG_DEBUG,
530 			"EAP-PEAP: Data appended to the message", encr_req);
531 	os_free(encr_req);
532 
533 	return data->ssl.tls_out;
534 }
535 
536 
537 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
538 {
539 	struct eap_peap_data *data = priv;
540 
541 	if (data->ssl.state == FRAG_ACK) {
542 		return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
543 						data->peap_version);
544 	}
545 
546 	if (data->ssl.state == WAIT_FRAG_ACK) {
547 		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
548 						data->peap_version, id);
549 	}
550 
551 	switch (data->state) {
552 	case START:
553 		return eap_peap_build_start(sm, data, id);
554 	case PHASE1:
555 	case PHASE1_ID2:
556 		if (tls_connection_established(sm->cfg->ssl_ctx,
557 					       data->ssl.conn)) {
558 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
559 				   "starting Phase2");
560 			eap_peap_state(data, PHASE2_START);
561 		}
562 		break;
563 	case PHASE2_ID:
564 	case PHASE2_METHOD:
565 		wpabuf_free(data->ssl.tls_out);
566 		data->ssl.tls_out_pos = 0;
567 		data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id);
568 		break;
569 #ifdef EAP_SERVER_TNC
570 	case PHASE2_SOH:
571 		wpabuf_free(data->ssl.tls_out);
572 		data->ssl.tls_out_pos = 0;
573 		data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id);
574 		break;
575 #endif /* EAP_SERVER_TNC */
576 	case PHASE2_TLV:
577 		wpabuf_free(data->ssl.tls_out);
578 		data->ssl.tls_out_pos = 0;
579 		data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id);
580 		break;
581 	case SUCCESS_REQ:
582 		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
583 							       1);
584 		break;
585 	case FAILURE_REQ:
586 		wpabuf_free(data->ssl.tls_out);
587 		data->ssl.tls_out_pos = 0;
588 		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
589 							       0);
590 		break;
591 	default:
592 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
593 			   __func__, data->state);
594 		return NULL;
595 	}
596 
597 	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
598 					data->peap_version, id);
599 }
600 
601 
602 static bool eap_peap_check(struct eap_sm *sm, void *priv,
603 			   struct wpabuf *respData)
604 {
605 	const u8 *pos;
606 	size_t len;
607 
608 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
609 	if (pos == NULL || len < 1) {
610 		wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
611 		return true;
612 	}
613 
614 	return false;
615 }
616 
617 
618 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
619 				int vendor, enum eap_type eap_type)
620 {
621 	if (data->phase2_priv && data->phase2_method) {
622 		data->phase2_method->reset(sm, data->phase2_priv);
623 		data->phase2_method = NULL;
624 		data->phase2_priv = NULL;
625 	}
626 	data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
627 	if (!data->phase2_method)
628 		return -1;
629 
630 	sm->init_phase2 = 1;
631 	data->phase2_priv = data->phase2_method->init(sm);
632 	sm->init_phase2 = 0;
633 	return 0;
634 }
635 
636 
637 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
638 					  struct eap_peap_data *data,
639 					  const u8 *crypto_tlv,
640 					  size_t crypto_tlv_len)
641 {
642 	u8 buf[61], mac[SHA1_MAC_LEN];
643 	const u8 *pos;
644 
645 	if (crypto_tlv_len != 4 + 56) {
646 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
647 			   "length %d", (int) crypto_tlv_len);
648 		return -1;
649 	}
650 
651 	pos = crypto_tlv;
652 	pos += 4; /* TLV header */
653 	if (pos[1] != data->peap_version) {
654 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
655 			   "mismatch (was %d; expected %d)",
656 			   pos[1], data->peap_version);
657 		return -1;
658 	}
659 
660 	if (pos[3] != 1) {
661 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
662 			   "SubType %d", pos[3]);
663 		return -1;
664 	}
665 	pos += 4;
666 	pos += 32; /* Nonce */
667 
668 	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
669 	os_memcpy(buf, crypto_tlv, 60);
670 	os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
671 	buf[60] = EAP_TYPE_PEAP;
672 	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
673 
674 	if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) {
675 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
676 			   "cryptobinding TLV");
677 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
678 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
679 			    buf, 61);
680 		return -1;
681 	}
682 
683 	wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
684 
685 	return 0;
686 }
687 
688 
689 static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
690 					struct eap_peap_data *data,
691 					struct wpabuf *in_data)
692 {
693 	const u8 *pos;
694 	size_t left;
695 	const u8 *result_tlv = NULL, *crypto_tlv = NULL;
696 	size_t result_tlv_len = 0, crypto_tlv_len = 0;
697 	int tlv_type, mandatory, tlv_len;
698 
699 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
700 	if (pos == NULL) {
701 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
702 		return;
703 	}
704 
705 	/* Parse TLVs */
706 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
707 	while (left >= 4) {
708 		mandatory = !!(pos[0] & 0x80);
709 		tlv_type = pos[0] & 0x3f;
710 		tlv_type = (tlv_type << 8) | pos[1];
711 		tlv_len = ((int) pos[2] << 8) | pos[3];
712 		pos += 4;
713 		left -= 4;
714 		if ((size_t) tlv_len > left) {
715 			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
716 				   "(tlv_len=%d left=%lu)", tlv_len,
717 				   (unsigned long) left);
718 			eap_peap_state(data, FAILURE);
719 			return;
720 		}
721 		switch (tlv_type) {
722 		case EAP_TLV_RESULT_TLV:
723 			result_tlv = pos;
724 			result_tlv_len = tlv_len;
725 			break;
726 		case EAP_TLV_CRYPTO_BINDING_TLV:
727 			crypto_tlv = pos;
728 			crypto_tlv_len = tlv_len;
729 			break;
730 		default:
731 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
732 				   "%d%s", tlv_type,
733 				   mandatory ? " (mandatory)" : "");
734 			if (mandatory) {
735 				eap_peap_state(data, FAILURE);
736 				return;
737 			}
738 			/* Ignore this TLV, but process other TLVs */
739 			break;
740 		}
741 
742 		pos += tlv_len;
743 		left -= tlv_len;
744 	}
745 	if (left) {
746 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
747 			   "Request (left=%lu)", (unsigned long) left);
748 		eap_peap_state(data, FAILURE);
749 		return;
750 	}
751 
752 	/* Process supported TLVs */
753 	if (crypto_tlv && data->crypto_binding_sent) {
754 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
755 			    crypto_tlv, crypto_tlv_len);
756 		if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
757 						   crypto_tlv_len + 4) < 0) {
758 			eap_peap_state(data, FAILURE);
759 			return;
760 		}
761 		data->crypto_binding_used = 1;
762 	} else if (!crypto_tlv && data->crypto_binding_sent &&
763 		   data->crypto_binding == REQUIRE_BINDING) {
764 		wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
765 		eap_peap_state(data, FAILURE);
766 		return;
767 	}
768 
769 	if (result_tlv) {
770 		int status;
771 		const char *requested;
772 
773 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
774 			    result_tlv, result_tlv_len);
775 		if (result_tlv_len < 2) {
776 			wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
777 				   "(len=%lu)",
778 				   (unsigned long) result_tlv_len);
779 			eap_peap_state(data, FAILURE);
780 			return;
781 		}
782 		requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
783 			"Failure";
784 		status = WPA_GET_BE16(result_tlv);
785 		if (status == EAP_TLV_RESULT_SUCCESS) {
786 			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
787 				   "- requested %s", requested);
788 			if (data->tlv_request == TLV_REQ_SUCCESS) {
789 				eap_peap_state(data, SUCCESS);
790 				eap_peap_valid_session(sm, data);
791 			} else {
792 				eap_peap_state(data, FAILURE);
793 			}
794 
795 		} else if (status == EAP_TLV_RESULT_FAILURE) {
796 			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
797 				   "- requested %s", requested);
798 			eap_peap_state(data, FAILURE);
799 		} else {
800 			wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
801 				   "Status %d", status);
802 			eap_peap_state(data, FAILURE);
803 		}
804 	}
805 }
806 
807 
808 #ifdef EAP_SERVER_TNC
809 static void eap_peap_process_phase2_soh(struct eap_sm *sm,
810 					struct eap_peap_data *data,
811 					struct wpabuf *in_data)
812 {
813 	const u8 *pos, *vpos;
814 	size_t left;
815 	const u8 *soh_tlv = NULL;
816 	size_t soh_tlv_len = 0;
817 	int tlv_type, mandatory, tlv_len, vtlv_len;
818 	u32 next_type;
819 	u32 vendor_id;
820 
821 	pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
822 	if (pos == NULL) {
823 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
824 			   "Extensions Method header - skip TNC");
825 		goto auth_method;
826 	}
827 
828 	/* Parse TLVs */
829 	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
830 	while (left >= 4) {
831 		mandatory = !!(pos[0] & 0x80);
832 		tlv_type = pos[0] & 0x3f;
833 		tlv_type = (tlv_type << 8) | pos[1];
834 		tlv_len = ((int) pos[2] << 8) | pos[3];
835 		pos += 4;
836 		left -= 4;
837 		if ((size_t) tlv_len > left) {
838 			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
839 				   "(tlv_len=%d left=%lu)", tlv_len,
840 				   (unsigned long) left);
841 			eap_peap_state(data, FAILURE);
842 			return;
843 		}
844 		switch (tlv_type) {
845 		case EAP_TLV_VENDOR_SPECIFIC_TLV:
846 			if (tlv_len < 4) {
847 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
848 					   "vendor specific TLV (len=%d)",
849 					   (int) tlv_len);
850 				eap_peap_state(data, FAILURE);
851 				return;
852 			}
853 
854 			vendor_id = WPA_GET_BE32(pos);
855 			if (vendor_id != EAP_VENDOR_MICROSOFT) {
856 				if (mandatory) {
857 					eap_peap_state(data, FAILURE);
858 					return;
859 				}
860 				break;
861 			}
862 
863 			vpos = pos + 4;
864 			mandatory = !!(vpos[0] & 0x80);
865 			tlv_type = vpos[0] & 0x3f;
866 			tlv_type = (tlv_type << 8) | vpos[1];
867 			vtlv_len = ((int) vpos[2] << 8) | vpos[3];
868 			vpos += 4;
869 			if (vpos + vtlv_len > pos + left) {
870 				wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
871 					   "underrun");
872 				eap_peap_state(data, FAILURE);
873 				return;
874 			}
875 
876 			if (tlv_type == 1) {
877 				soh_tlv = vpos;
878 				soh_tlv_len = vtlv_len;
879 				break;
880 			}
881 
882 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
883 				   "Type %d%s", tlv_type,
884 				   mandatory ? " (mandatory)" : "");
885 			if (mandatory) {
886 				eap_peap_state(data, FAILURE);
887 				return;
888 			}
889 			/* Ignore this TLV, but process other TLVs */
890 			break;
891 		default:
892 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
893 				   "%d%s", tlv_type,
894 				   mandatory ? " (mandatory)" : "");
895 			if (mandatory) {
896 				eap_peap_state(data, FAILURE);
897 				return;
898 			}
899 			/* Ignore this TLV, but process other TLVs */
900 			break;
901 		}
902 
903 		pos += tlv_len;
904 		left -= tlv_len;
905 	}
906 	if (left) {
907 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
908 			   "Request (left=%lu)", (unsigned long) left);
909 		eap_peap_state(data, FAILURE);
910 		return;
911 	}
912 
913 	/* Process supported TLVs */
914 	if (soh_tlv) {
915 		int failure = 0;
916 		wpabuf_free(data->soh_response);
917 		data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
918 						      &failure);
919 		if (failure) {
920 			eap_peap_state(data, FAILURE);
921 			return;
922 		}
923 	} else {
924 		wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
925 		eap_peap_state(data, FAILURE);
926 		return;
927 	}
928 
929 auth_method:
930 	eap_peap_state(data, PHASE2_METHOD);
931 	next_type = sm->user->methods[0].method;
932 	sm->user_eap_method_index = 1;
933 	wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
934 		   sm->user->methods[0].vendor, next_type);
935 	eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
936 }
937 #endif /* EAP_SERVER_TNC */
938 
939 
940 static void eap_peap_process_phase2_response(struct eap_sm *sm,
941 					     struct eap_peap_data *data,
942 					     struct wpabuf *in_data)
943 {
944 	int next_vendor = EAP_VENDOR_IETF;
945 	u32 next_type = EAP_TYPE_NONE;
946 	const struct eap_hdr *hdr;
947 	const u8 *pos;
948 	size_t left;
949 
950 	if (data->state == PHASE2_TLV) {
951 		eap_peap_process_phase2_tlv(sm, data, in_data);
952 		return;
953 	}
954 
955 #ifdef EAP_SERVER_TNC
956 	if (data->state == PHASE2_SOH) {
957 		eap_peap_process_phase2_soh(sm, data, in_data);
958 		return;
959 	}
960 #endif /* EAP_SERVER_TNC */
961 
962 	if (data->phase2_priv == NULL) {
963 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
964 			   "initialized?!", __func__);
965 		return;
966 	}
967 
968 	hdr = wpabuf_head(in_data);
969 	pos = (const u8 *) (hdr + 1);
970 
971 	if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
972 		left = wpabuf_len(in_data) - sizeof(*hdr);
973 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
974 			    "allowed types", pos + 1, left - 1);
975 		eap_sm_process_nak(sm, pos + 1, left - 1);
976 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
977 		    (sm->user->methods[sm->user_eap_method_index].vendor !=
978 		     EAP_VENDOR_IETF ||
979 		     sm->user->methods[sm->user_eap_method_index].method !=
980 		     EAP_TYPE_NONE)) {
981 			next_vendor = sm->user->methods[
982 				sm->user_eap_method_index].vendor;
983 			next_type = sm->user->methods[
984 				sm->user_eap_method_index++].method;
985 			wpa_printf(MSG_DEBUG,
986 				   "EAP-PEAP: try EAP vendor %d type 0x%x",
987 				   next_vendor, next_type);
988 		} else {
989 			eap_peap_req_failure(sm, data);
990 			next_vendor = EAP_VENDOR_IETF;
991 			next_type = EAP_TYPE_NONE;
992 		}
993 		eap_peap_phase2_init(sm, data, next_vendor, next_type);
994 		return;
995 	}
996 
997 	if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
998 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
999 			   "ignore the packet");
1000 		return;
1001 	}
1002 
1003 	data->phase2_method->process(sm, data->phase2_priv, in_data);
1004 
1005 	if (sm->method_pending == METHOD_PENDING_WAIT) {
1006 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
1007 			   "pending wait state - save decrypted response");
1008 		wpabuf_free(data->pending_phase2_resp);
1009 		data->pending_phase2_resp = wpabuf_dup(in_data);
1010 	}
1011 
1012 	if (!data->phase2_method->isDone(sm, data->phase2_priv))
1013 		return;
1014 
1015 	if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
1016 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
1017 		eap_peap_req_failure(sm, data);
1018 		next_vendor = EAP_VENDOR_IETF;
1019 		next_type = EAP_TYPE_NONE;
1020 		eap_peap_phase2_init(sm, data, next_vendor, next_type);
1021 		return;
1022 	}
1023 
1024 	os_free(data->phase2_key);
1025 	if (data->phase2_method->getKey) {
1026 		data->phase2_key = data->phase2_method->getKey(
1027 			sm, data->phase2_priv, &data->phase2_key_len);
1028 		if (data->phase2_key == NULL) {
1029 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
1030 				   "failed");
1031 			eap_peap_req_failure(sm, data);
1032 			eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1033 					     EAP_TYPE_NONE);
1034 			return;
1035 		}
1036 	}
1037 
1038 	switch (data->state) {
1039 	case PHASE1_ID2:
1040 	case PHASE2_ID:
1041 	case PHASE2_SOH:
1042 		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1043 			wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
1044 					  "Identity not found in the user "
1045 					  "database",
1046 					  sm->identity, sm->identity_len);
1047 			eap_peap_req_failure(sm, data);
1048 			next_vendor = EAP_VENDOR_IETF;
1049 			next_type = EAP_TYPE_NONE;
1050 			break;
1051 		}
1052 
1053 #ifdef EAP_SERVER_TNC
1054 		if (data->state != PHASE2_SOH && sm->cfg->tnc &&
1055 		    data->peap_version == 0) {
1056 			eap_peap_state(data, PHASE2_SOH);
1057 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
1058 				   "TNC (NAP SOH)");
1059 			next_vendor = EAP_VENDOR_IETF;
1060 			next_type = EAP_TYPE_NONE;
1061 			break;
1062 		}
1063 #endif /* EAP_SERVER_TNC */
1064 
1065 		eap_peap_state(data, PHASE2_METHOD);
1066 		next_vendor = sm->user->methods[0].vendor;
1067 		next_type = sm->user->methods[0].method;
1068 		sm->user_eap_method_index = 1;
1069 		wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
1070 			   next_vendor, next_type);
1071 		break;
1072 	case PHASE2_METHOD:
1073 		eap_peap_req_success(sm, data);
1074 		next_vendor = EAP_VENDOR_IETF;
1075 		next_type = EAP_TYPE_NONE;
1076 		break;
1077 	case FAILURE:
1078 		break;
1079 	default:
1080 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
1081 			   __func__, data->state);
1082 		break;
1083 	}
1084 
1085 	eap_peap_phase2_init(sm, data, next_vendor, next_type);
1086 }
1087 
1088 
1089 static void eap_peap_process_phase2(struct eap_sm *sm,
1090 				    struct eap_peap_data *data,
1091 				    const struct wpabuf *respData,
1092 				    struct wpabuf *in_buf)
1093 {
1094 	struct wpabuf *in_decrypted;
1095 	const struct eap_hdr *hdr;
1096 	size_t len;
1097 
1098 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1099 		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
1100 
1101 	if (data->pending_phase2_resp) {
1102 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1103 			   "skip decryption and use old data");
1104 		eap_peap_process_phase2_response(sm, data,
1105 						 data->pending_phase2_resp);
1106 		wpabuf_free(data->pending_phase2_resp);
1107 		data->pending_phase2_resp = NULL;
1108 		return;
1109 	}
1110 
1111 	in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
1112 					      in_buf);
1113 	if (in_decrypted == NULL) {
1114 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1115 			   "data");
1116 		eap_peap_state(data, FAILURE);
1117 		return;
1118 	}
1119 
1120 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1121 			    in_decrypted);
1122 
1123 	if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1124 		const struct eap_hdr *resp;
1125 		struct eap_hdr *nhdr;
1126 		struct wpabuf *nbuf =
1127 			wpabuf_alloc(sizeof(struct eap_hdr) +
1128 				     wpabuf_len(in_decrypted));
1129 		if (nbuf == NULL) {
1130 			wpabuf_free(in_decrypted);
1131 			return;
1132 		}
1133 
1134 		resp = wpabuf_head(respData);
1135 		nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1136 		nhdr->code = resp->code;
1137 		nhdr->identifier = resp->identifier;
1138 		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1139 					    wpabuf_len(in_decrypted));
1140 		wpabuf_put_buf(nbuf, in_decrypted);
1141 		wpabuf_free(in_decrypted);
1142 
1143 		in_decrypted = nbuf;
1144 	}
1145 
1146 	hdr = wpabuf_head(in_decrypted);
1147 	if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1148 		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1149 			   "EAP frame (len=%lu)",
1150 			   (unsigned long) wpabuf_len(in_decrypted));
1151 		wpabuf_free(in_decrypted);
1152 		eap_peap_req_failure(sm, data);
1153 		return;
1154 	}
1155 	len = be_to_host16(hdr->length);
1156 	if (len > wpabuf_len(in_decrypted)) {
1157 		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1158 			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1159 			   (unsigned long) wpabuf_len(in_decrypted),
1160 			   (unsigned long) len);
1161 		wpabuf_free(in_decrypted);
1162 		eap_peap_req_failure(sm, data);
1163 		return;
1164 	}
1165 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1166 		   "identifier=%d length=%lu", hdr->code, hdr->identifier,
1167 		   (unsigned long) len);
1168 	switch (hdr->code) {
1169 	case EAP_CODE_RESPONSE:
1170 		eap_peap_process_phase2_response(sm, data, in_decrypted);
1171 		break;
1172 	case EAP_CODE_SUCCESS:
1173 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1174 		if (data->state == SUCCESS_REQ) {
1175 			eap_peap_state(data, SUCCESS);
1176 			eap_peap_valid_session(sm, data);
1177 		}
1178 		break;
1179 	case EAP_CODE_FAILURE:
1180 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1181 		eap_peap_state(data, FAILURE);
1182 		break;
1183 	default:
1184 		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1185 			   "Phase 2 EAP header", hdr->code);
1186 		break;
1187 	}
1188 
1189 	wpabuf_free(in_decrypted);
1190 }
1191 
1192 
1193 static int eap_peap_process_version(struct eap_sm *sm, void *priv,
1194 				    int peer_version)
1195 {
1196 	struct eap_peap_data *data = priv;
1197 
1198 	data->recv_version = peer_version;
1199 	if (data->force_version >= 0 && peer_version != data->force_version) {
1200 		wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1201 			   " version (forced=%d peer=%d) - reject",
1202 			   data->force_version, peer_version);
1203 		return -1;
1204 	}
1205 	if (peer_version < data->peap_version) {
1206 		wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1207 			   "use version %d",
1208 			   peer_version, data->peap_version, peer_version);
1209 		data->peap_version = peer_version;
1210 	}
1211 
1212 	return 0;
1213 }
1214 
1215 
1216 static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
1217 				 const struct wpabuf *respData)
1218 {
1219 	struct eap_peap_data *data = priv;
1220 
1221 	switch (data->state) {
1222 	case PHASE1:
1223 		if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1224 			eap_peap_state(data, FAILURE);
1225 			break;
1226 		}
1227 		break;
1228 	case PHASE2_START:
1229 		eap_peap_state(data, PHASE2_ID);
1230 		eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1231 				     EAP_TYPE_IDENTITY);
1232 		break;
1233 	case PHASE1_ID2:
1234 	case PHASE2_ID:
1235 	case PHASE2_METHOD:
1236 	case PHASE2_SOH:
1237 	case PHASE2_TLV:
1238 		eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in);
1239 		break;
1240 	case SUCCESS_REQ:
1241 		eap_peap_state(data, SUCCESS);
1242 		eap_peap_valid_session(sm, data);
1243 		break;
1244 	case FAILURE_REQ:
1245 		eap_peap_state(data, FAILURE);
1246 		break;
1247 	default:
1248 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1249 			   data->state, __func__);
1250 		break;
1251 	}
1252 }
1253 
1254 
1255 static void eap_peap_process(struct eap_sm *sm, void *priv,
1256 			     struct wpabuf *respData)
1257 {
1258 	struct eap_peap_data *data = priv;
1259 	const struct wpabuf *buf;
1260 	const u8 *pos;
1261 	u8 id_len;
1262 
1263 	if (eap_server_tls_process(sm, &data->ssl, respData, data,
1264 				   EAP_TYPE_PEAP, eap_peap_process_version,
1265 				   eap_peap_process_msg) < 0) {
1266 		eap_peap_state(data, FAILURE);
1267 		return;
1268 	}
1269 
1270 	if (data->state == SUCCESS ||
1271 	    !tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
1272 	    !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
1273 		return;
1274 
1275 	buf = tls_connection_get_success_data(data->ssl.conn);
1276 	if (!buf || wpabuf_len(buf) < 2) {
1277 		wpa_printf(MSG_DEBUG,
1278 			   "EAP-PEAP: No success data in resumed session - reject attempt");
1279 		eap_peap_state(data, FAILURE);
1280 		return;
1281 	}
1282 
1283 	pos = wpabuf_head(buf);
1284 	if (*pos != EAP_TYPE_PEAP) {
1285 		wpa_printf(MSG_DEBUG,
1286 			   "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt",
1287 			   *pos);
1288 		eap_peap_state(data, FAILURE);
1289 		return;
1290 	}
1291 
1292 	pos++;
1293 	id_len = *pos++;
1294 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session",
1295 			  pos, id_len);
1296 	os_free(sm->identity);
1297 	sm->identity = os_malloc(id_len ? id_len : 1);
1298 	if (!sm->identity) {
1299 		sm->identity_len = 0;
1300 		eap_peap_state(data, FAILURE);
1301 		return;
1302 	}
1303 
1304 	os_memcpy(sm->identity, pos, id_len);
1305 	sm->identity_len = id_len;
1306 
1307 	if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1308 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database",
1309 				  sm->identity, sm->identity_len);
1310 		eap_peap_state(data, FAILURE);
1311 		return;
1312 	}
1313 
1314 	wpa_printf(MSG_DEBUG,
1315 		   "EAP-PEAP: Resuming previous session - skip Phase2");
1316 	eap_peap_req_success(sm, data);
1317 	if (data->state == SUCCESS_REQ)
1318 		tls_connection_set_success_data_resumed(data->ssl.conn);
1319 }
1320 
1321 
1322 static bool eap_peap_isDone(struct eap_sm *sm, void *priv)
1323 {
1324 	struct eap_peap_data *data = priv;
1325 	return data->state == SUCCESS || data->state == FAILURE;
1326 }
1327 
1328 
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 *eapKeyData;
1333 	const char *label;
1334 	const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
1335 	const u8 *context = NULL;
1336 	size_t context_len = 0;
1337 
1338 	if (data->state != SUCCESS)
1339 		return NULL;
1340 
1341 	if (data->crypto_binding_used) {
1342 		u8 csk[128];
1343 		/*
1344 		 * Note: It looks like Microsoft implementation requires null
1345 		 * termination for this label while the one used for deriving
1346 		 * IPMK|CMK did not use null termination.
1347 		 */
1348 		if (peap_prfplus(data->peap_version, data->ipmk, 40,
1349 				 "Session Key Generating Function",
1350 				 (u8 *) "\00", 1, csk, sizeof(csk)) < 0)
1351 			return NULL;
1352 		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1353 		eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1354 		if (eapKeyData) {
1355 			os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1356 			*len = EAP_TLS_KEY_LEN;
1357 			wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1358 				    eapKeyData, EAP_TLS_KEY_LEN);
1359 		} else {
1360 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1361 				   "key");
1362 		}
1363 
1364 		forced_memzero(csk, sizeof(csk));
1365 
1366 		return eapKeyData;
1367 	}
1368 
1369 	if (data->ssl.tls_v13) {
1370 		label = "EXPORTER_EAP_TLS_Key_Material";
1371 		context = eap_tls13_context;
1372 		context_len = sizeof(eap_tls13_context);
1373 	} else {
1374 		/* TODO: PEAPv1 - different label in some cases */
1375 		label = "client EAP encryption";
1376 	}
1377 
1378 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1379 					       label, context, context_len,
1380 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1381 	if (eapKeyData) {
1382 		os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
1383 		*len = EAP_TLS_KEY_LEN;
1384 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1385 			    eapKeyData, EAP_TLS_KEY_LEN);
1386 	} else {
1387 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1388 	}
1389 
1390 	return eapKeyData;
1391 }
1392 
1393 
1394 static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1395 {
1396 	struct eap_peap_data *data = priv;
1397 	u8 *eapKeyData, *emsk;
1398 	const char *label;
1399 	const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
1400 	const u8 *context = NULL;
1401 	size_t context_len = 0;
1402 
1403 	if (data->state != SUCCESS)
1404 		return NULL;
1405 
1406 	if (data->crypto_binding_used) {
1407 		/* [MS-PEAP] does not define EMSK derivation */
1408 		return NULL;
1409 	}
1410 
1411 	if (data->ssl.tls_v13) {
1412 		label = "EXPORTER_EAP_TLS_Key_Material";
1413 		context = eap_tls13_context;
1414 		context_len = sizeof(eap_tls13_context);
1415 	} else {
1416 		/* TODO: PEAPv1 - different label in some cases */
1417 		label = "client EAP encryption";
1418 	}
1419 
1420 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1421 					       label, context, context_len,
1422 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1423 	if (eapKeyData) {
1424 		emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
1425 		bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1426 		if (!emsk)
1427 			return NULL;
1428 		*len = EAP_EMSK_LEN;
1429 		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived EMSK",
1430 			    emsk, EAP_EMSK_LEN);
1431 	} else {
1432 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive EMSK");
1433 		emsk = NULL;
1434 	}
1435 
1436 	return emsk;
1437 }
1438 
1439 
1440 static bool eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1441 {
1442 	struct eap_peap_data *data = priv;
1443 	return data->state == SUCCESS;
1444 }
1445 
1446 
1447 static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1448 {
1449 	struct eap_peap_data *data = priv;
1450 
1451 	if (data->state != SUCCESS)
1452 		return NULL;
1453 
1454 	return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP,
1455 						len);
1456 }
1457 
1458 
1459 int eap_server_peap_register(void)
1460 {
1461 	struct eap_method *eap;
1462 
1463 	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1464 				      EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1465 	if (eap == NULL)
1466 		return -1;
1467 
1468 	eap->init = eap_peap_init;
1469 	eap->reset = eap_peap_reset;
1470 	eap->buildReq = eap_peap_buildReq;
1471 	eap->check = eap_peap_check;
1472 	eap->process = eap_peap_process;
1473 	eap->isDone = eap_peap_isDone;
1474 	eap->getKey = eap_peap_getKey;
1475 	eap->get_emsk = eap_peap_get_emsk;
1476 	eap->isSuccess = eap_peap_isSuccess;
1477 	eap->getSessionId = eap_peap_get_session_id;
1478 
1479 	return eap_server_method_register(eap);
1480 }
1481