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