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
29static void eap_peap_reset(struct eap_sm *sm, void *priv);
30
31
32struct 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
59static 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
92static 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
103static void eap_peap_valid_session(struct eap_sm *sm,
104				   struct eap_peap_data *data)
105{
106	struct wpabuf *buf;
107
108	if (!sm->tls_session_lifetime ||
109	    tls_connection_resumed(sm->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
132static 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
149static 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
167static 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
195static 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
210static 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
232static 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
268static 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
307static 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
323static 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
329	/*
330	 * Tunnel key (TK) is the first 60 octets of the key generated by
331	 * phase 1 of PEAP (based on TLS).
332	 */
333	tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
334				       NULL, 0, EAP_TLS_KEY_LEN);
335	if (tk == NULL)
336		return -1;
337	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
338
339	if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
340		/* Fast-connect: IPMK|CMK = TK */
341		os_memcpy(data->ipmk, tk, 40);
342		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
343				data->ipmk, 40);
344		os_memcpy(data->cmk, tk + 40, 20);
345		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
346				data->cmk, 20);
347		os_free(tk);
348		return 0;
349	}
350
351	eap_peap_get_isk(data, isk, sizeof(isk));
352	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
353
354	/*
355	 * IPMK Seed = "Inner Methods Compound Keys" | ISK
356	 * TempKey = First 40 octets of TK
357	 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
358	 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
359	 * in the end of the label just before ISK; is that just a typo?)
360	 */
361	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
362	res = peap_prfplus(data->peap_version, tk, 40,
363			   "Inner Methods Compound Keys",
364			   isk, sizeof(isk), imck, sizeof(imck));
365	forced_memzero(isk, sizeof(isk));
366	if (res < 0) {
367		os_free(tk);
368		return -1;
369	}
370	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
371			imck, sizeof(imck));
372
373	os_free(tk);
374
375	os_memcpy(data->ipmk, imck, 40);
376	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
377	os_memcpy(data->cmk, imck + 40, 20);
378	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
379	forced_memzero(imck, sizeof(imck));
380
381	return 0;
382}
383
384
385static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
386						 struct eap_peap_data *data,
387						 u8 id)
388{
389	struct wpabuf *buf, *encr_req;
390	size_t mlen;
391
392	mlen = 6; /* Result TLV */
393	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
394	    data->crypto_binding != NO_BINDING) {
395		mlen += 60; /* Cryptobinding TLV */
396#ifdef EAP_SERVER_TNC
397		if (data->soh_response)
398			mlen += wpabuf_len(data->soh_response);
399#endif /* EAP_SERVER_TNC */
400	}
401
402	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen,
403			    EAP_CODE_REQUEST, id);
404	if (buf == NULL)
405		return NULL;
406
407	wpabuf_put_u8(buf, 0x80); /* Mandatory */
408	wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
409	/* Length */
410	wpabuf_put_be16(buf, 2);
411	/* Status */
412	wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
413			EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
414
415	if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
416	    data->crypto_binding != NO_BINDING) {
417		u8 *mac;
418		u8 eap_type = EAP_TYPE_PEAP;
419		const u8 *addr[2];
420		size_t len[2];
421		u16 tlv_type;
422
423#ifdef EAP_SERVER_TNC
424		if (data->soh_response) {
425			wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
426				   "Response TLV");
427			wpabuf_put_buf(buf, data->soh_response);
428			wpabuf_free(data->soh_response);
429			data->soh_response = NULL;
430		}
431#endif /* EAP_SERVER_TNC */
432
433		if (eap_peap_derive_cmk(sm, data) < 0 ||
434		    random_get_bytes(data->binding_nonce, 32)) {
435			wpabuf_free(buf);
436			return NULL;
437		}
438
439		/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
440		addr[0] = wpabuf_put(buf, 0);
441		len[0] = 60;
442		addr[1] = &eap_type;
443		len[1] = 1;
444
445		tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
446		wpabuf_put_be16(buf, tlv_type);
447		wpabuf_put_be16(buf, 56);
448
449		wpabuf_put_u8(buf, 0); /* Reserved */
450		wpabuf_put_u8(buf, data->peap_version); /* Version */
451		wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
452		wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
453		wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
454		mac = wpabuf_put(buf, 20); /* Compound_MAC */
455		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
456			    data->cmk, 20);
457		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
458			    addr[0], len[0]);
459		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
460			    addr[1], len[1]);
461		hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
462		wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
463			    mac, SHA1_MAC_LEN);
464		data->crypto_binding_sent = 1;
465	}
466
467	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
468			    buf);
469
470	encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
471	wpabuf_free(buf);
472
473	return encr_req;
474}
475
476
477static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
478						  struct eap_peap_data *data,
479						  u8 id, int success)
480{
481	struct wpabuf *encr_req, msgbuf;
482	size_t req_len;
483	struct eap_hdr *hdr;
484
485	req_len = sizeof(*hdr);
486	hdr = os_zalloc(req_len);
487	if (hdr == NULL)
488		return NULL;
489
490	hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
491	hdr->identifier = id;
492	hdr->length = host_to_be16(req_len);
493
494	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
495			(u8 *) hdr, req_len);
496
497	wpabuf_set(&msgbuf, hdr, req_len);
498	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
499	os_free(hdr);
500
501	return encr_req;
502}
503
504
505static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
506{
507	struct eap_peap_data *data = priv;
508
509	if (data->ssl.state == FRAG_ACK) {
510		return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
511						data->peap_version);
512	}
513
514	if (data->ssl.state == WAIT_FRAG_ACK) {
515		return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
516						data->peap_version, id);
517	}
518
519	switch (data->state) {
520	case START:
521		return eap_peap_build_start(sm, data, id);
522	case PHASE1:
523	case PHASE1_ID2:
524		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
525			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
526				   "starting Phase2");
527			eap_peap_state(data, PHASE2_START);
528		}
529		break;
530	case PHASE2_ID:
531	case PHASE2_METHOD:
532		wpabuf_free(data->ssl.tls_out);
533		data->ssl.tls_out_pos = 0;
534		data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id);
535		break;
536#ifdef EAP_SERVER_TNC
537	case PHASE2_SOH:
538		wpabuf_free(data->ssl.tls_out);
539		data->ssl.tls_out_pos = 0;
540		data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id);
541		break;
542#endif /* EAP_SERVER_TNC */
543	case PHASE2_TLV:
544		wpabuf_free(data->ssl.tls_out);
545		data->ssl.tls_out_pos = 0;
546		data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id);
547		break;
548	case SUCCESS_REQ:
549		wpabuf_free(data->ssl.tls_out);
550		data->ssl.tls_out_pos = 0;
551		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
552							       1);
553		break;
554	case FAILURE_REQ:
555		wpabuf_free(data->ssl.tls_out);
556		data->ssl.tls_out_pos = 0;
557		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
558							       0);
559		break;
560	default:
561		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
562			   __func__, data->state);
563		return NULL;
564	}
565
566	return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
567					data->peap_version, id);
568}
569
570
571static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
572			      struct wpabuf *respData)
573{
574	const u8 *pos;
575	size_t len;
576
577	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
578	if (pos == NULL || len < 1) {
579		wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
580		return TRUE;
581	}
582
583	return FALSE;
584}
585
586
587static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
588				int vendor, EapType eap_type)
589{
590	if (data->phase2_priv && data->phase2_method) {
591		data->phase2_method->reset(sm, data->phase2_priv);
592		data->phase2_method = NULL;
593		data->phase2_priv = NULL;
594	}
595	data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
596	if (!data->phase2_method)
597		return -1;
598
599	sm->init_phase2 = 1;
600	data->phase2_priv = data->phase2_method->init(sm);
601	sm->init_phase2 = 0;
602	return 0;
603}
604
605
606static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
607					  struct eap_peap_data *data,
608					  const u8 *crypto_tlv,
609					  size_t crypto_tlv_len)
610{
611	u8 buf[61], mac[SHA1_MAC_LEN];
612	const u8 *pos;
613
614	if (crypto_tlv_len != 4 + 56) {
615		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
616			   "length %d", (int) crypto_tlv_len);
617		return -1;
618	}
619
620	pos = crypto_tlv;
621	pos += 4; /* TLV header */
622	if (pos[1] != data->peap_version) {
623		wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
624			   "mismatch (was %d; expected %d)",
625			   pos[1], data->peap_version);
626		return -1;
627	}
628
629	if (pos[3] != 1) {
630		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
631			   "SubType %d", pos[3]);
632		return -1;
633	}
634	pos += 4;
635	pos += 32; /* Nonce */
636
637	/* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
638	os_memcpy(buf, crypto_tlv, 60);
639	os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
640	buf[60] = EAP_TYPE_PEAP;
641	hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
642
643	if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) {
644		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
645			   "cryptobinding TLV");
646		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
647		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
648			    buf, 61);
649		return -1;
650	}
651
652	wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
653
654	return 0;
655}
656
657
658static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
659					struct eap_peap_data *data,
660					struct wpabuf *in_data)
661{
662	const u8 *pos;
663	size_t left;
664	const u8 *result_tlv = NULL, *crypto_tlv = NULL;
665	size_t result_tlv_len = 0, crypto_tlv_len = 0;
666	int tlv_type, mandatory, tlv_len;
667
668	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
669	if (pos == NULL) {
670		wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
671		return;
672	}
673
674	/* Parse TLVs */
675	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
676	while (left >= 4) {
677		mandatory = !!(pos[0] & 0x80);
678		tlv_type = pos[0] & 0x3f;
679		tlv_type = (tlv_type << 8) | pos[1];
680		tlv_len = ((int) pos[2] << 8) | pos[3];
681		pos += 4;
682		left -= 4;
683		if ((size_t) tlv_len > left) {
684			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
685				   "(tlv_len=%d left=%lu)", tlv_len,
686				   (unsigned long) left);
687			eap_peap_state(data, FAILURE);
688			return;
689		}
690		switch (tlv_type) {
691		case EAP_TLV_RESULT_TLV:
692			result_tlv = pos;
693			result_tlv_len = tlv_len;
694			break;
695		case EAP_TLV_CRYPTO_BINDING_TLV:
696			crypto_tlv = pos;
697			crypto_tlv_len = tlv_len;
698			break;
699		default:
700			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
701				   "%d%s", tlv_type,
702				   mandatory ? " (mandatory)" : "");
703			if (mandatory) {
704				eap_peap_state(data, FAILURE);
705				return;
706			}
707			/* Ignore this TLV, but process other TLVs */
708			break;
709		}
710
711		pos += tlv_len;
712		left -= tlv_len;
713	}
714	if (left) {
715		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
716			   "Request (left=%lu)", (unsigned long) left);
717		eap_peap_state(data, FAILURE);
718		return;
719	}
720
721	/* Process supported TLVs */
722	if (crypto_tlv && data->crypto_binding_sent) {
723		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
724			    crypto_tlv, crypto_tlv_len);
725		if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
726						   crypto_tlv_len + 4) < 0) {
727			eap_peap_state(data, FAILURE);
728			return;
729		}
730		data->crypto_binding_used = 1;
731	} else if (!crypto_tlv && data->crypto_binding_sent &&
732		   data->crypto_binding == REQUIRE_BINDING) {
733		wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
734		eap_peap_state(data, FAILURE);
735		return;
736	}
737
738	if (result_tlv) {
739		int status;
740		const char *requested;
741
742		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
743			    result_tlv, result_tlv_len);
744		if (result_tlv_len < 2) {
745			wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
746				   "(len=%lu)",
747				   (unsigned long) result_tlv_len);
748			eap_peap_state(data, FAILURE);
749			return;
750		}
751		requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
752			"Failure";
753		status = WPA_GET_BE16(result_tlv);
754		if (status == EAP_TLV_RESULT_SUCCESS) {
755			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
756				   "- requested %s", requested);
757			if (data->tlv_request == TLV_REQ_SUCCESS) {
758				eap_peap_state(data, SUCCESS);
759				eap_peap_valid_session(sm, data);
760			} else {
761				eap_peap_state(data, FAILURE);
762			}
763
764		} else if (status == EAP_TLV_RESULT_FAILURE) {
765			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
766				   "- requested %s", requested);
767			eap_peap_state(data, FAILURE);
768		} else {
769			wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
770				   "Status %d", status);
771			eap_peap_state(data, FAILURE);
772		}
773	}
774}
775
776
777#ifdef EAP_SERVER_TNC
778static void eap_peap_process_phase2_soh(struct eap_sm *sm,
779					struct eap_peap_data *data,
780					struct wpabuf *in_data)
781{
782	const u8 *pos, *vpos;
783	size_t left;
784	const u8 *soh_tlv = NULL;
785	size_t soh_tlv_len = 0;
786	int tlv_type, mandatory, tlv_len, vtlv_len;
787	u32 next_type;
788	u32 vendor_id;
789
790	pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
791	if (pos == NULL) {
792		wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
793			   "Extensions Method header - skip TNC");
794		goto auth_method;
795	}
796
797	/* Parse TLVs */
798	wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
799	while (left >= 4) {
800		mandatory = !!(pos[0] & 0x80);
801		tlv_type = pos[0] & 0x3f;
802		tlv_type = (tlv_type << 8) | pos[1];
803		tlv_len = ((int) pos[2] << 8) | pos[3];
804		pos += 4;
805		left -= 4;
806		if ((size_t) tlv_len > left) {
807			wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
808				   "(tlv_len=%d left=%lu)", tlv_len,
809				   (unsigned long) left);
810			eap_peap_state(data, FAILURE);
811			return;
812		}
813		switch (tlv_type) {
814		case EAP_TLV_VENDOR_SPECIFIC_TLV:
815			if (tlv_len < 4) {
816				wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
817					   "vendor specific TLV (len=%d)",
818					   (int) tlv_len);
819				eap_peap_state(data, FAILURE);
820				return;
821			}
822
823			vendor_id = WPA_GET_BE32(pos);
824			if (vendor_id != EAP_VENDOR_MICROSOFT) {
825				if (mandatory) {
826					eap_peap_state(data, FAILURE);
827					return;
828				}
829				break;
830			}
831
832			vpos = pos + 4;
833			mandatory = !!(vpos[0] & 0x80);
834			tlv_type = vpos[0] & 0x3f;
835			tlv_type = (tlv_type << 8) | vpos[1];
836			vtlv_len = ((int) vpos[2] << 8) | vpos[3];
837			vpos += 4;
838			if (vpos + vtlv_len > pos + left) {
839				wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
840					   "underrun");
841				eap_peap_state(data, FAILURE);
842				return;
843			}
844
845			if (tlv_type == 1) {
846				soh_tlv = vpos;
847				soh_tlv_len = vtlv_len;
848				break;
849			}
850
851			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
852				   "Type %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		default:
861			wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
862				   "%d%s", tlv_type,
863				   mandatory ? " (mandatory)" : "");
864			if (mandatory) {
865				eap_peap_state(data, FAILURE);
866				return;
867			}
868			/* Ignore this TLV, but process other TLVs */
869			break;
870		}
871
872		pos += tlv_len;
873		left -= tlv_len;
874	}
875	if (left) {
876		wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
877			   "Request (left=%lu)", (unsigned long) left);
878		eap_peap_state(data, FAILURE);
879		return;
880	}
881
882	/* Process supported TLVs */
883	if (soh_tlv) {
884		int failure = 0;
885		wpabuf_free(data->soh_response);
886		data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
887						      &failure);
888		if (failure) {
889			eap_peap_state(data, FAILURE);
890			return;
891		}
892	} else {
893		wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
894		eap_peap_state(data, FAILURE);
895		return;
896	}
897
898auth_method:
899	eap_peap_state(data, PHASE2_METHOD);
900	next_type = sm->user->methods[0].method;
901	sm->user_eap_method_index = 1;
902	wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
903		   sm->user->methods[0].vendor, next_type);
904	eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
905}
906#endif /* EAP_SERVER_TNC */
907
908
909static void eap_peap_process_phase2_response(struct eap_sm *sm,
910					     struct eap_peap_data *data,
911					     struct wpabuf *in_data)
912{
913	int next_vendor = EAP_VENDOR_IETF;
914	u32 next_type = EAP_TYPE_NONE;
915	const struct eap_hdr *hdr;
916	const u8 *pos;
917	size_t left;
918
919	if (data->state == PHASE2_TLV) {
920		eap_peap_process_phase2_tlv(sm, data, in_data);
921		return;
922	}
923
924#ifdef EAP_SERVER_TNC
925	if (data->state == PHASE2_SOH) {
926		eap_peap_process_phase2_soh(sm, data, in_data);
927		return;
928	}
929#endif /* EAP_SERVER_TNC */
930
931	if (data->phase2_priv == NULL) {
932		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
933			   "initialized?!", __func__);
934		return;
935	}
936
937	hdr = wpabuf_head(in_data);
938	pos = (const u8 *) (hdr + 1);
939
940	if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
941		left = wpabuf_len(in_data) - sizeof(*hdr);
942		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
943			    "allowed types", pos + 1, left - 1);
944		eap_sm_process_nak(sm, pos + 1, left - 1);
945		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
946		    (sm->user->methods[sm->user_eap_method_index].vendor !=
947		     EAP_VENDOR_IETF ||
948		     sm->user->methods[sm->user_eap_method_index].method !=
949		     EAP_TYPE_NONE)) {
950			next_vendor = sm->user->methods[
951				sm->user_eap_method_index].vendor;
952			next_type = sm->user->methods[
953				sm->user_eap_method_index++].method;
954			wpa_printf(MSG_DEBUG,
955				   "EAP-PEAP: try EAP vendor %d type 0x%x",
956				   next_vendor, next_type);
957		} else {
958			eap_peap_req_failure(sm, data);
959			next_vendor = EAP_VENDOR_IETF;
960			next_type = EAP_TYPE_NONE;
961		}
962		eap_peap_phase2_init(sm, data, next_vendor, next_type);
963		return;
964	}
965
966	if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
967		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
968			   "ignore the packet");
969		return;
970	}
971
972	data->phase2_method->process(sm, data->phase2_priv, in_data);
973
974	if (sm->method_pending == METHOD_PENDING_WAIT) {
975		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
976			   "pending wait state - save decrypted response");
977		wpabuf_free(data->pending_phase2_resp);
978		data->pending_phase2_resp = wpabuf_dup(in_data);
979	}
980
981	if (!data->phase2_method->isDone(sm, data->phase2_priv))
982		return;
983
984	if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
985		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
986		eap_peap_req_failure(sm, data);
987		next_vendor = EAP_VENDOR_IETF;
988		next_type = EAP_TYPE_NONE;
989		eap_peap_phase2_init(sm, data, next_vendor, next_type);
990		return;
991	}
992
993	os_free(data->phase2_key);
994	if (data->phase2_method->getKey) {
995		data->phase2_key = data->phase2_method->getKey(
996			sm, data->phase2_priv, &data->phase2_key_len);
997		if (data->phase2_key == NULL) {
998			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
999				   "failed");
1000			eap_peap_req_failure(sm, data);
1001			eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1002					     EAP_TYPE_NONE);
1003			return;
1004		}
1005	}
1006
1007	switch (data->state) {
1008	case PHASE1_ID2:
1009	case PHASE2_ID:
1010	case PHASE2_SOH:
1011		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1012			wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
1013					  "Identity not found in the user "
1014					  "database",
1015					  sm->identity, sm->identity_len);
1016			eap_peap_req_failure(sm, data);
1017			next_vendor = EAP_VENDOR_IETF;
1018			next_type = EAP_TYPE_NONE;
1019			break;
1020		}
1021
1022#ifdef EAP_SERVER_TNC
1023		if (data->state != PHASE2_SOH && sm->tnc &&
1024		    data->peap_version == 0) {
1025			eap_peap_state(data, PHASE2_SOH);
1026			wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
1027				   "TNC (NAP SOH)");
1028			next_vendor = EAP_VENDOR_IETF;
1029			next_type = EAP_TYPE_NONE;
1030			break;
1031		}
1032#endif /* EAP_SERVER_TNC */
1033
1034		eap_peap_state(data, PHASE2_METHOD);
1035		next_vendor = sm->user->methods[0].vendor;
1036		next_type = sm->user->methods[0].method;
1037		sm->user_eap_method_index = 1;
1038		wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
1039			   next_vendor, next_type);
1040		break;
1041	case PHASE2_METHOD:
1042		eap_peap_req_success(sm, data);
1043		next_vendor = EAP_VENDOR_IETF;
1044		next_type = EAP_TYPE_NONE;
1045		break;
1046	case FAILURE:
1047		break;
1048	default:
1049		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
1050			   __func__, data->state);
1051		break;
1052	}
1053
1054	eap_peap_phase2_init(sm, data, next_vendor, next_type);
1055}
1056
1057
1058static void eap_peap_process_phase2(struct eap_sm *sm,
1059				    struct eap_peap_data *data,
1060				    const struct wpabuf *respData,
1061				    struct wpabuf *in_buf)
1062{
1063	struct wpabuf *in_decrypted;
1064	const struct eap_hdr *hdr;
1065	size_t len;
1066
1067	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1068		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
1069
1070	if (data->pending_phase2_resp) {
1071		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1072			   "skip decryption and use old data");
1073		eap_peap_process_phase2_response(sm, data,
1074						 data->pending_phase2_resp);
1075		wpabuf_free(data->pending_phase2_resp);
1076		data->pending_phase2_resp = NULL;
1077		return;
1078	}
1079
1080	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
1081					      in_buf);
1082	if (in_decrypted == NULL) {
1083		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1084			   "data");
1085		eap_peap_state(data, FAILURE);
1086		return;
1087	}
1088
1089	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1090			    in_decrypted);
1091
1092	if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1093		const struct eap_hdr *resp;
1094		struct eap_hdr *nhdr;
1095		struct wpabuf *nbuf =
1096			wpabuf_alloc(sizeof(struct eap_hdr) +
1097				     wpabuf_len(in_decrypted));
1098		if (nbuf == NULL) {
1099			wpabuf_free(in_decrypted);
1100			return;
1101		}
1102
1103		resp = wpabuf_head(respData);
1104		nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1105		nhdr->code = resp->code;
1106		nhdr->identifier = resp->identifier;
1107		nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1108					    wpabuf_len(in_decrypted));
1109		wpabuf_put_buf(nbuf, in_decrypted);
1110		wpabuf_free(in_decrypted);
1111
1112		in_decrypted = nbuf;
1113	}
1114
1115	hdr = wpabuf_head(in_decrypted);
1116	if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1117		wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1118			   "EAP frame (len=%lu)",
1119			   (unsigned long) wpabuf_len(in_decrypted));
1120		wpabuf_free(in_decrypted);
1121		eap_peap_req_failure(sm, data);
1122		return;
1123	}
1124	len = be_to_host16(hdr->length);
1125	if (len > wpabuf_len(in_decrypted)) {
1126		wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1127			   "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1128			   (unsigned long) wpabuf_len(in_decrypted),
1129			   (unsigned long) len);
1130		wpabuf_free(in_decrypted);
1131		eap_peap_req_failure(sm, data);
1132		return;
1133	}
1134	wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1135		   "identifier=%d length=%lu", hdr->code, hdr->identifier,
1136		   (unsigned long) len);
1137	switch (hdr->code) {
1138	case EAP_CODE_RESPONSE:
1139		eap_peap_process_phase2_response(sm, data, in_decrypted);
1140		break;
1141	case EAP_CODE_SUCCESS:
1142		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1143		if (data->state == SUCCESS_REQ) {
1144			eap_peap_state(data, SUCCESS);
1145			eap_peap_valid_session(sm, data);
1146		}
1147		break;
1148	case EAP_CODE_FAILURE:
1149		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1150		eap_peap_state(data, FAILURE);
1151		break;
1152	default:
1153		wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1154			   "Phase 2 EAP header", hdr->code);
1155		break;
1156	}
1157
1158	wpabuf_free(in_decrypted);
1159}
1160
1161
1162static int eap_peap_process_version(struct eap_sm *sm, void *priv,
1163				    int peer_version)
1164{
1165	struct eap_peap_data *data = priv;
1166
1167	data->recv_version = peer_version;
1168	if (data->force_version >= 0 && peer_version != data->force_version) {
1169		wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1170			   " version (forced=%d peer=%d) - reject",
1171			   data->force_version, peer_version);
1172		return -1;
1173	}
1174	if (peer_version < data->peap_version) {
1175		wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1176			   "use version %d",
1177			   peer_version, data->peap_version, peer_version);
1178		data->peap_version = peer_version;
1179	}
1180
1181	return 0;
1182}
1183
1184
1185static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
1186				 const struct wpabuf *respData)
1187{
1188	struct eap_peap_data *data = priv;
1189
1190	switch (data->state) {
1191	case PHASE1:
1192		if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1193			eap_peap_state(data, FAILURE);
1194			break;
1195		}
1196		break;
1197	case PHASE2_START:
1198		eap_peap_state(data, PHASE2_ID);
1199		eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1200				     EAP_TYPE_IDENTITY);
1201		break;
1202	case PHASE1_ID2:
1203	case PHASE2_ID:
1204	case PHASE2_METHOD:
1205	case PHASE2_SOH:
1206	case PHASE2_TLV:
1207		eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in);
1208		break;
1209	case SUCCESS_REQ:
1210		eap_peap_state(data, SUCCESS);
1211		eap_peap_valid_session(sm, data);
1212		break;
1213	case FAILURE_REQ:
1214		eap_peap_state(data, FAILURE);
1215		break;
1216	default:
1217		wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1218			   data->state, __func__);
1219		break;
1220	}
1221}
1222
1223
1224static void eap_peap_process(struct eap_sm *sm, void *priv,
1225			     struct wpabuf *respData)
1226{
1227	struct eap_peap_data *data = priv;
1228	const struct wpabuf *buf;
1229	const u8 *pos;
1230	u8 id_len;
1231
1232	if (eap_server_tls_process(sm, &data->ssl, respData, data,
1233				   EAP_TYPE_PEAP, eap_peap_process_version,
1234				   eap_peap_process_msg) < 0) {
1235		eap_peap_state(data, FAILURE);
1236		return;
1237	}
1238
1239	if (data->state == SUCCESS ||
1240	    !tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
1241	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
1242		return;
1243
1244	buf = tls_connection_get_success_data(data->ssl.conn);
1245	if (!buf || wpabuf_len(buf) < 2) {
1246		wpa_printf(MSG_DEBUG,
1247			   "EAP-PEAP: No success data in resumed session - reject attempt");
1248		eap_peap_state(data, FAILURE);
1249		return;
1250	}
1251
1252	pos = wpabuf_head(buf);
1253	if (*pos != EAP_TYPE_PEAP) {
1254		wpa_printf(MSG_DEBUG,
1255			   "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt",
1256			   *pos);
1257		eap_peap_state(data, FAILURE);
1258		return;
1259	}
1260
1261	pos++;
1262	id_len = *pos++;
1263	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session",
1264			  pos, id_len);
1265	os_free(sm->identity);
1266	sm->identity = os_malloc(id_len ? id_len : 1);
1267	if (!sm->identity) {
1268		sm->identity_len = 0;
1269		eap_peap_state(data, FAILURE);
1270		return;
1271	}
1272
1273	os_memcpy(sm->identity, pos, id_len);
1274	sm->identity_len = id_len;
1275
1276	if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1277		wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database",
1278				  sm->identity, sm->identity_len);
1279		eap_peap_state(data, FAILURE);
1280		return;
1281	}
1282
1283	wpa_printf(MSG_DEBUG,
1284		   "EAP-PEAP: Resuming previous session - skip Phase2");
1285	eap_peap_req_success(sm, data);
1286	if (data->state == SUCCESS_REQ)
1287		tls_connection_set_success_data_resumed(data->ssl.conn);
1288}
1289
1290
1291static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv)
1292{
1293	struct eap_peap_data *data = priv;
1294	return data->state == SUCCESS || data->state == FAILURE;
1295}
1296
1297
1298static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1299{
1300	struct eap_peap_data *data = priv;
1301	u8 *eapKeyData;
1302
1303	if (data->state != SUCCESS)
1304		return NULL;
1305
1306	if (data->crypto_binding_used) {
1307		u8 csk[128];
1308		/*
1309		 * Note: It looks like Microsoft implementation requires null
1310		 * termination for this label while the one used for deriving
1311		 * IPMK|CMK did not use null termination.
1312		 */
1313		if (peap_prfplus(data->peap_version, data->ipmk, 40,
1314				 "Session Key Generating Function",
1315				 (u8 *) "\00", 1, csk, sizeof(csk)) < 0)
1316			return NULL;
1317		wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1318		eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1319		if (eapKeyData) {
1320			os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1321			*len = EAP_TLS_KEY_LEN;
1322			wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1323				    eapKeyData, EAP_TLS_KEY_LEN);
1324		} else {
1325			wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1326				   "key");
1327		}
1328
1329		forced_memzero(csk, sizeof(csk));
1330
1331		return eapKeyData;
1332	}
1333
1334	/* TODO: PEAPv1 - different label in some cases */
1335	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1336					       "client EAP encryption", NULL, 0,
1337					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1338	if (eapKeyData) {
1339		os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
1340		*len = EAP_TLS_KEY_LEN;
1341		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1342			    eapKeyData, EAP_TLS_KEY_LEN);
1343	} else {
1344		wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1345	}
1346
1347	return eapKeyData;
1348}
1349
1350
1351static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1352{
1353	struct eap_peap_data *data = priv;
1354	u8 *eapKeyData, *emsk;
1355
1356	if (data->state != SUCCESS)
1357		return NULL;
1358
1359	if (data->crypto_binding_used) {
1360		/* [MS-PEAP] does not define EMSK derivation */
1361		return NULL;
1362	}
1363
1364	/* TODO: PEAPv1 - different label in some cases */
1365	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1366					       "client EAP encryption", NULL, 0,
1367					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1368	if (eapKeyData) {
1369		emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
1370		bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1371		if (!emsk)
1372			return NULL;
1373		*len = EAP_EMSK_LEN;
1374		wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived EMSK",
1375			    emsk, EAP_EMSK_LEN);
1376	} else {
1377		wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive EMSK");
1378		emsk = NULL;
1379	}
1380
1381	return emsk;
1382}
1383
1384
1385static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1386{
1387	struct eap_peap_data *data = priv;
1388	return data->state == SUCCESS;
1389}
1390
1391
1392static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1393{
1394	struct eap_peap_data *data = priv;
1395
1396	if (data->state != SUCCESS)
1397		return NULL;
1398
1399	return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP,
1400						len);
1401}
1402
1403
1404int eap_server_peap_register(void)
1405{
1406	struct eap_method *eap;
1407
1408	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1409				      EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1410	if (eap == NULL)
1411		return -1;
1412
1413	eap->init = eap_peap_init;
1414	eap->reset = eap_peap_reset;
1415	eap->buildReq = eap_peap_buildReq;
1416	eap->check = eap_peap_check;
1417	eap->process = eap_peap_process;
1418	eap->isDone = eap_peap_isDone;
1419	eap->getKey = eap_peap_getKey;
1420	eap->get_emsk = eap_peap_get_emsk;
1421	eap->isSuccess = eap_peap_isSuccess;
1422	eap->getSessionId = eap_peap_get_session_id;
1423
1424	return eap_server_method_register(eap);
1425}
1426