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