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