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->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
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	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
399static 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
491static 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
537static 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
602static 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
618static 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
637static 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
689static 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
809static 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
929auth_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
940static 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
1089static 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
1193static 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
1216static 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
1255static 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
1322static 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
1329static 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
1394static 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
1440static 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
1447static 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
1459int 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