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