1 /*
2  * EAP peer method: EAP-TEAP (RFC 7170)
3  * Copyright (c) 2004-2024, 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/tls.h"
13 #include "eap_common/eap_teap_common.h"
14 #include "eap_i.h"
15 #include "eap_tls_common.h"
16 #include "eap_config.h"
17 
18 
19 static void eap_teap_deinit(struct eap_sm *sm, void *priv);
20 
21 
22 struct eap_teap_data {
23 	struct eap_ssl_data ssl;
24 
25 	u8 teap_version; /* Negotiated version */
26 	u8 received_version; /* Version number received during negotiation */
27 	u16 tls_cs;
28 
29 	const struct eap_method *phase2_method;
30 	void *phase2_priv;
31 	int phase2_success;
32 	int inner_method_done;
33 	int iresult_verified;
34 	int result_success_done;
35 	int on_tx_completion;
36 
37 	struct eap_method_type phase2_type;
38 	struct eap_method_type *phase2_types;
39 	size_t num_phase2_types;
40 	int resuming; /* starting a resumed session */
41 	int test_outer_tlvs;
42 
43 	u8 key_data[EAP_TEAP_KEY_LEN];
44 	u8 *session_id;
45 	size_t id_len;
46 	u8 emsk[EAP_EMSK_LEN];
47 	int success;
48 
49 	u8 simck[EAP_TEAP_SIMCK_LEN];
50 	u8 simck_msk[EAP_TEAP_SIMCK_LEN];
51 	u8 simck_emsk[EAP_TEAP_SIMCK_LEN];
52 	int simck_idx;
53 	bool cmk_emsk_available;
54 
55 	struct wpabuf *pending_phase2_req;
56 	struct wpabuf *pending_resp;
57 	struct wpabuf *server_outer_tlvs;
58 	struct wpabuf *peer_outer_tlvs;
59 
60 	enum teap_compat {
61 		TEAP_DEFAULT,
62 		TEAP_FREERADIUS,
63 	} teap_compat;
64 };
65 
66 
eap_teap_parse_phase1(struct eap_teap_data * data,const char * phase1)67 static void eap_teap_parse_phase1(struct eap_teap_data *data,
68 				  const char *phase1)
69 {
70 #ifdef CONFIG_TESTING_OPTIONS
71 	if (os_strstr(phase1, "teap_test_outer_tlvs=1"))
72 		data->test_outer_tlvs = 1;
73 #endif /* CONFIG_TESTING_OPTIONS */
74 
75 	if (os_strstr(phase1, "teap_compat=freeradius"))
76 		data->teap_compat = TEAP_FREERADIUS;
77 }
78 
79 
eap_teap_init(struct eap_sm * sm)80 static void * eap_teap_init(struct eap_sm *sm)
81 {
82 	struct eap_teap_data *data;
83 	struct eap_peer_config *config = eap_get_config(sm);
84 
85 	if (!config)
86 		return NULL;
87 
88 	data = os_zalloc(sizeof(*data));
89 	if (!data)
90 		return NULL;
91 	data->teap_version = EAP_TEAP_VERSION;
92 
93 	if (config->phase1)
94 		eap_teap_parse_phase1(data, config->phase1);
95 
96 	if (eap_peer_select_phase2_methods(config, "auth=",
97 					   &data->phase2_types,
98 					   &data->num_phase2_types, 0) < 0) {
99 		eap_teap_deinit(sm, data);
100 		return NULL;
101 	}
102 
103 	data->phase2_type.vendor = EAP_VENDOR_IETF;
104 	data->phase2_type.method = EAP_TYPE_NONE;
105 
106 	if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TEAP)) {
107 		wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL");
108 		eap_teap_deinit(sm, data);
109 		return NULL;
110 	}
111 
112 	return data;
113 }
114 
115 
eap_teap_clear(struct eap_teap_data * data)116 static void eap_teap_clear(struct eap_teap_data *data)
117 {
118 	forced_memzero(data->key_data, EAP_TEAP_KEY_LEN);
119 	forced_memzero(data->emsk, EAP_EMSK_LEN);
120 	os_free(data->session_id);
121 	data->session_id = NULL;
122 	wpabuf_free(data->pending_phase2_req);
123 	data->pending_phase2_req = NULL;
124 	wpabuf_free(data->pending_resp);
125 	data->pending_resp = NULL;
126 	wpabuf_free(data->server_outer_tlvs);
127 	data->server_outer_tlvs = NULL;
128 	wpabuf_free(data->peer_outer_tlvs);
129 	data->peer_outer_tlvs = NULL;
130 	forced_memzero(data->simck, EAP_TEAP_SIMCK_LEN);
131 	forced_memzero(data->simck_msk, EAP_TEAP_SIMCK_LEN);
132 	forced_memzero(data->simck_emsk, EAP_TEAP_SIMCK_LEN);
133 }
134 
135 
eap_teap_deinit(struct eap_sm * sm,void * priv)136 static void eap_teap_deinit(struct eap_sm *sm, void *priv)
137 {
138 	struct eap_teap_data *data = priv;
139 
140 	if (!data)
141 		return;
142 	if (data->phase2_priv && data->phase2_method)
143 		data->phase2_method->deinit(sm, data->phase2_priv);
144 	eap_teap_clear(data);
145 	os_free(data->phase2_types);
146 	eap_peer_tls_ssl_deinit(sm, &data->ssl);
147 
148 	os_free(data);
149 }
150 
151 
eap_teap_derive_msk(struct eap_teap_data * data)152 static int eap_teap_derive_msk(struct eap_teap_data *data)
153 {
154 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Derive MSK/EMSK (n=%d)",
155 		   data->simck_idx);
156 	wpa_hexdump(MSG_DEBUG, "EAP-TEAP: S-IMCK[n]", data->simck,
157 		    EAP_TEAP_SIMCK_LEN);
158 
159 	if (eap_teap_derive_eap_msk(data->tls_cs, data->simck,
160 				    data->key_data) < 0 ||
161 	    eap_teap_derive_eap_emsk(data->tls_cs, data->simck,
162 				     data->emsk) < 0)
163 		return -1;
164 	data->success = 1;
165 	return 0;
166 }
167 
168 
eap_teap_derive_key_auth(struct eap_sm * sm,struct eap_teap_data * data)169 static int eap_teap_derive_key_auth(struct eap_sm *sm,
170 				    struct eap_teap_data *data)
171 {
172 	int res;
173 
174 	/* RFC 7170, Section 5.1 */
175 	res = tls_connection_export_key(sm->ssl_ctx, data->ssl.conn,
176 					TEAP_TLS_EXPORTER_LABEL_SKS, NULL, 0,
177 					data->simck, EAP_TEAP_SIMCK_LEN);
178 	if (res)
179 		return res;
180 	wpa_hexdump_key(MSG_DEBUG,
181 			"EAP-TEAP: session_key_seed (S-IMCK[0])",
182 			data->simck, EAP_TEAP_SIMCK_LEN);
183 	os_memcpy(data->simck_msk, data->simck, EAP_TEAP_SIMCK_LEN);
184 	os_memcpy(data->simck_emsk, data->simck, EAP_TEAP_SIMCK_LEN);
185 	data->simck_idx = 0;
186 	return 0;
187 }
188 
189 
eap_teap_init_phase2_method(struct eap_sm * sm,struct eap_teap_data * data)190 static int eap_teap_init_phase2_method(struct eap_sm *sm,
191 				       struct eap_teap_data *data)
192 {
193 	data->inner_method_done = 0;
194 	data->iresult_verified = 0;
195 	data->phase2_method =
196 		eap_peer_get_eap_method(data->phase2_type.vendor,
197 					data->phase2_type.method);
198 	if (!data->phase2_method)
199 		return -1;
200 
201 	/* While RFC 7170 does not describe this, EAP-TEAP has been deployed
202 	 * with implementations that use the EAP-FAST-MSCHAPv2, instead of the
203 	 * EAP-MSCHAPv2, way of deriving the MSK for IMSK. Use that design here
204 	 * to interoperate.
205 	 */
206 	sm->eap_fast_mschapv2 = true;
207 
208 	sm->init_phase2 = 1;
209 	data->phase2_priv = data->phase2_method->init(sm);
210 	sm->init_phase2 = 0;
211 
212 	return data->phase2_priv == NULL ? -1 : 0;
213 }
214 
215 
eap_teap_select_phase2_method(struct eap_teap_data * data,int vendor,enum eap_type type)216 static int eap_teap_select_phase2_method(struct eap_teap_data *data,
217 					 int vendor, enum eap_type type)
218 {
219 	size_t i;
220 
221 #ifdef EAP_TNC
222 	if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_TNC) {
223 		data->phase2_type.vendor = EAP_VENDOR_IETF;
224 		data->phase2_type.method = EAP_TYPE_TNC;
225 		wpa_printf(MSG_DEBUG,
226 			   "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
227 			   data->phase2_type.vendor,
228 			   data->phase2_type.method);
229 		return 0;
230 	}
231 #endif /* EAP_TNC */
232 
233 	for (i = 0; i < data->num_phase2_types; i++) {
234 		if (data->phase2_types[i].vendor != vendor ||
235 		    data->phase2_types[i].method != type)
236 			continue;
237 
238 		data->phase2_type.vendor = data->phase2_types[i].vendor;
239 		data->phase2_type.method = data->phase2_types[i].method;
240 		wpa_printf(MSG_DEBUG,
241 			   "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
242 			   data->phase2_type.vendor,
243 			   data->phase2_type.method);
244 		break;
245 	}
246 
247 	if (vendor != data->phase2_type.vendor ||
248 	    type != data->phase2_type.method ||
249 	    (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_NONE))
250 		return -1;
251 
252 	return 0;
253 }
254 
255 
eap_teap_deinit_inner_eap(struct eap_sm * sm,struct eap_teap_data * data)256 static void eap_teap_deinit_inner_eap(struct eap_sm *sm,
257 				      struct eap_teap_data *data)
258 {
259 	if (!data->phase2_priv || !data->phase2_method)
260 		return;
261 
262 	wpa_printf(MSG_DEBUG,
263 		   "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
264 	data->phase2_method->deinit(sm, data->phase2_priv);
265 	data->phase2_method = NULL;
266 	data->phase2_priv = NULL;
267 	data->phase2_type.vendor = EAP_VENDOR_IETF;
268 	data->phase2_type.method = EAP_TYPE_NONE;
269 }
270 
271 
eap_teap_phase2_request(struct eap_sm * sm,struct eap_teap_data * data,struct eap_method_ret * ret,struct eap_hdr * hdr,struct wpabuf ** resp)272 static int eap_teap_phase2_request(struct eap_sm *sm,
273 				   struct eap_teap_data *data,
274 				   struct eap_method_ret *ret,
275 				   struct eap_hdr *hdr,
276 				   struct wpabuf **resp)
277 {
278 	size_t len = be_to_host16(hdr->length);
279 	u8 *pos;
280 	struct eap_method_ret iret;
281 	struct eap_peer_config *config = eap_get_config(sm);
282 	struct wpabuf msg;
283 	int vendor = EAP_VENDOR_IETF;
284 	enum eap_type method;
285 
286 	if (len <= sizeof(struct eap_hdr)) {
287 		wpa_printf(MSG_INFO,
288 			   "EAP-TEAP: too short Phase 2 request (len=%lu)",
289 			   (unsigned long) len);
290 		return -1;
291 	}
292 	pos = (u8 *) (hdr + 1);
293 	method = *pos;
294 	if (method == EAP_TYPE_EXPANDED) {
295 		if (len < sizeof(struct eap_hdr) + 8) {
296 			wpa_printf(MSG_INFO,
297 				   "EAP-TEAP: Too short Phase 2 request (expanded header) (len=%lu)",
298 				   (unsigned long) len);
299 			return -1;
300 		}
301 		vendor = WPA_GET_BE24(pos + 1);
302 		method = WPA_GET_BE32(pos + 4);
303 	}
304 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%u:%u",
305 		   vendor, method);
306 	if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_IDENTITY) {
307 		eap_teap_deinit_inner_eap(sm, data);
308 		*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
309 		return 0;
310 	}
311 
312 	if (data->phase2_priv && data->phase2_method &&
313 	    (vendor != data->phase2_type.vendor ||
314 	     method != data->phase2_type.method))
315 		eap_teap_deinit_inner_eap(sm, data);
316 
317 	if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
318 	    data->phase2_type.method == EAP_TYPE_NONE &&
319 	    eap_teap_select_phase2_method(data, vendor, method) < 0) {
320 		if (eap_peer_tls_phase2_nak(data->phase2_types,
321 					    data->num_phase2_types,
322 					    hdr, resp))
323 			return -1;
324 		return 0;
325 	}
326 
327 	if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
328 	    !data->phase2_method) {
329 		wpa_printf(MSG_INFO,
330 			   "EAP-TEAP: Failed to initialize Phase 2 EAP method %u:%u",
331 			   vendor, method);
332 		ret->methodState = METHOD_DONE;
333 		ret->decision = DECISION_FAIL;
334 		return -1;
335 	}
336 
337 	os_memset(&iret, 0, sizeof(iret));
338 	wpabuf_set(&msg, hdr, len);
339 	*resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
340 					     &msg);
341 	if (iret.methodState == METHOD_DONE)
342 		data->inner_method_done = 1;
343 	if (!(*resp) ||
344 	    (iret.methodState == METHOD_DONE &&
345 	     iret.decision == DECISION_FAIL)) {
346 		/* Wait for protected indication of failure */
347 		ret->methodState = METHOD_MAY_CONT;
348 		ret->decision = DECISION_FAIL;
349 	} else if ((iret.methodState == METHOD_DONE ||
350 		    iret.methodState == METHOD_MAY_CONT) &&
351 		   (iret.decision == DECISION_UNCOND_SUCC ||
352 		    iret.decision == DECISION_COND_SUCC)) {
353 		data->phase2_success = 1;
354 	}
355 
356 	if (!(*resp) && config &&
357 	    (config->pending_req_identity || config->pending_req_password ||
358 	     config->pending_req_otp || config->pending_req_new_password ||
359 	     config->pending_req_sim)) {
360 		wpabuf_free(data->pending_phase2_req);
361 		data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
362 	} else if (!(*resp))
363 		return -1;
364 
365 	return 0;
366 }
367 
368 
eap_teap_tlv_nak(int vendor_id,int tlv_type)369 static struct wpabuf * eap_teap_tlv_nak(int vendor_id, int tlv_type)
370 {
371 	struct wpabuf *buf;
372 	struct teap_tlv_nak *nak;
373 
374 	wpa_printf(MSG_DEBUG,
375 		   "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
376 		   vendor_id, tlv_type);
377 	buf = wpabuf_alloc(sizeof(*nak));
378 	if (!buf)
379 		return NULL;
380 	nak = wpabuf_put(buf, sizeof(*nak));
381 	nak->tlv_type = host_to_be16(TEAP_TLV_MANDATORY | TEAP_TLV_NAK);
382 	nak->length = host_to_be16(6);
383 	nak->vendor_id = host_to_be32(vendor_id);
384 	nak->nak_type = host_to_be16(tlv_type);
385 	return buf;
386 }
387 
388 
eap_teap_add_identity_type(struct eap_sm * sm,struct wpabuf * msg)389 static struct wpabuf * eap_teap_add_identity_type(struct eap_sm *sm,
390 						  struct wpabuf *msg)
391 {
392 	struct wpabuf *tlv;
393 
394 	tlv = eap_teap_tlv_identity_type(sm->use_machine_cred ?
395 					 TEAP_IDENTITY_TYPE_MACHINE :
396 					 TEAP_IDENTITY_TYPE_USER);
397 	return wpabuf_concat(msg, tlv);
398 }
399 
400 
eap_teap_process_eap_payload_tlv(struct eap_sm * sm,struct eap_teap_data * data,struct eap_method_ret * ret,u8 * eap_payload_tlv,size_t eap_payload_tlv_len,enum teap_identity_types req_id_type)401 static struct wpabuf * eap_teap_process_eap_payload_tlv(
402 	struct eap_sm *sm, struct eap_teap_data *data,
403 	struct eap_method_ret *ret,
404 	u8 *eap_payload_tlv, size_t eap_payload_tlv_len,
405 	enum teap_identity_types req_id_type)
406 {
407 	struct eap_hdr *hdr;
408 	struct wpabuf *resp = NULL;
409 
410 	if (eap_payload_tlv_len < sizeof(*hdr)) {
411 		wpa_printf(MSG_DEBUG,
412 			   "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
413 			   (unsigned long) eap_payload_tlv_len);
414 		return NULL;
415 	}
416 
417 	hdr = (struct eap_hdr *) eap_payload_tlv;
418 	if (be_to_host16(hdr->length) > eap_payload_tlv_len) {
419 		wpa_printf(MSG_DEBUG,
420 			   "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
421 		return NULL;
422 	}
423 
424 	if (hdr->code != EAP_CODE_REQUEST) {
425 		wpa_printf(MSG_INFO,
426 			   "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
427 			   hdr->code);
428 		return NULL;
429 	}
430 
431 	if (eap_teap_phase2_request(sm, data, ret, hdr, &resp)) {
432 		wpa_printf(MSG_INFO,
433 			   "EAP-TEAP: Phase 2 Request processing failed");
434 		return NULL;
435 	}
436 
437 	resp = eap_teap_tlv_eap_payload(resp);
438 	if (req_id_type)
439 		resp = eap_teap_add_identity_type(sm, resp);
440 
441 	return resp;
442 }
443 
444 
eap_teap_process_basic_auth_req(struct eap_sm * sm,struct eap_teap_data * data,u8 * basic_auth_req,size_t basic_auth_req_len,enum teap_identity_types req_id_type)445 static struct wpabuf * eap_teap_process_basic_auth_req(
446 	struct eap_sm *sm, struct eap_teap_data *data,
447 	u8 *basic_auth_req, size_t basic_auth_req_len,
448 	enum teap_identity_types req_id_type)
449 {
450 	const u8 *identity, *password;
451 	size_t identity_len, password_len, plen;
452 	struct wpabuf *resp;
453 
454 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Req prompt",
455 			  basic_auth_req, basic_auth_req_len);
456 	/* TODO: send over control interface */
457 
458 	identity = eap_get_config_identity(sm, &identity_len);
459 	password = eap_get_config_password(sm, &password_len);
460 	if (!identity || !password ||
461 	    identity_len > 255 || password_len > 255) {
462 		wpa_printf(MSG_DEBUG,
463 			   "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
464 		return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ);
465 	}
466 
467 	plen = 1 + identity_len + 1 + password_len;
468 	resp = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + plen);
469 	if (!resp)
470 		return NULL;
471 	eap_teap_put_tlv_hdr(resp, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP, plen);
472 	wpabuf_put_u8(resp, identity_len);
473 	wpabuf_put_data(resp, identity, identity_len);
474 	wpabuf_put_u8(resp, password_len);
475 	wpabuf_put_data(resp, password, password_len);
476 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Resp",
477 			    resp);
478 	if (req_id_type)
479 		resp = eap_teap_add_identity_type(sm, resp);
480 
481 	/* Assume this succeeds so that Result TLV(Success) from the server can
482 	 * be used to terminate TEAP. */
483 	data->phase2_success = 1;
484 
485 	return resp;
486 }
487 
488 
489 static int
eap_teap_validate_crypto_binding(struct eap_teap_data * data,const struct teap_tlv_crypto_binding * cb)490 eap_teap_validate_crypto_binding(struct eap_teap_data *data,
491 				 const struct teap_tlv_crypto_binding *cb)
492 {
493 	u8 flags, subtype;
494 
495 	subtype = cb->subtype & 0x0f;
496 	flags = cb->subtype >> 4;
497 
498 	wpa_printf(MSG_DEBUG,
499 		   "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
500 		   cb->version, cb->received_version, flags, subtype);
501 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
502 		    cb->nonce, sizeof(cb->nonce));
503 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
504 		    cb->emsk_compound_mac, sizeof(cb->emsk_compound_mac));
505 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
506 		    cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
507 
508 	if (cb->version != EAP_TEAP_VERSION ||
509 	    cb->received_version != data->received_version ||
510 	    subtype != TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST ||
511 	    flags < 1 || flags > 3) {
512 		wpa_printf(MSG_INFO,
513 			   "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
514 			   cb->version, cb->received_version, flags, subtype);
515 		return -1;
516 	}
517 
518 	if (cb->nonce[EAP_TEAP_NONCE_LEN - 1] & 0x01) {
519 		wpa_printf(MSG_INFO,
520 			   "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
521 		return -1;
522 	}
523 
524 	return 0;
525 }
526 
527 
eap_teap_write_crypto_binding(struct eap_teap_data * data,struct teap_tlv_crypto_binding * rbind,const struct teap_tlv_crypto_binding * cb,const u8 * cmk_msk,const u8 * cmk_emsk)528 static int eap_teap_write_crypto_binding(
529 	struct eap_teap_data *data,
530 	struct teap_tlv_crypto_binding *rbind,
531 	const struct teap_tlv_crypto_binding *cb,
532 	const u8 *cmk_msk, const u8 *cmk_emsk)
533 {
534 	u8 subtype, flags;
535 
536 	rbind->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
537 				       TEAP_TLV_CRYPTO_BINDING);
538 	rbind->length = host_to_be16(sizeof(*rbind) -
539 				     sizeof(struct teap_tlv_hdr));
540 	rbind->version = EAP_TEAP_VERSION;
541 	rbind->received_version = data->received_version;
542 	subtype = TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE;
543 	if (cmk_emsk)
544 		flags = TEAP_CRYPTO_BINDING_EMSK_CMAC;
545 	else if (cmk_msk)
546 		flags = TEAP_CRYPTO_BINDING_MSK_CMAC;
547 	else
548 		return -1;
549 	rbind->subtype = (flags << 4) | subtype;
550 	os_memcpy(rbind->nonce, cb->nonce, sizeof(cb->nonce));
551 	inc_byte_array(rbind->nonce, sizeof(rbind->nonce));
552 	os_memset(rbind->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
553 	os_memset(rbind->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
554 
555 	if (cmk_msk &&
556 	    eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
557 				  data->peer_outer_tlvs, cmk_msk,
558 				  rbind->msk_compound_mac) < 0)
559 		return -1;
560 	if (cmk_emsk &&
561 	    eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
562 				  data->peer_outer_tlvs, cmk_emsk,
563 				  rbind->emsk_compound_mac) < 0)
564 		return -1;
565 
566 	wpa_printf(MSG_DEBUG,
567 		   "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
568 		   rbind->version, rbind->received_version, flags, subtype);
569 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
570 		    rbind->nonce, sizeof(rbind->nonce));
571 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
572 		    rbind->emsk_compound_mac, sizeof(rbind->emsk_compound_mac));
573 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
574 		    rbind->msk_compound_mac, sizeof(rbind->msk_compound_mac));
575 
576 	return 0;
577 }
578 
579 
eap_teap_get_cmk(struct eap_sm * sm,struct eap_teap_data * data,u8 * cmk_msk,u8 * cmk_emsk)580 static int eap_teap_get_cmk(struct eap_sm *sm, struct eap_teap_data *data,
581 			    u8 *cmk_msk, u8 *cmk_emsk)
582 {
583 	u8 *msk = NULL, *emsk = NULL;
584 	size_t msk_len = 0, emsk_len = 0;
585 	int res;
586 
587 	wpa_printf(MSG_DEBUG,
588 		   "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
589 		   data->simck_idx + 1);
590 
591 	if (!data->phase2_method)
592 		goto out; /* no MSK derived in Basic-Password-Auth */
593 
594 	if (!data->phase2_method || !data->phase2_priv) {
595 		wpa_printf(MSG_INFO, "EAP-TEAP: Phase 2 method not available");
596 		return -1;
597 	}
598 
599 	if (data->phase2_method->isKeyAvailable &&
600 	    !data->phase2_method->isKeyAvailable(sm, data->phase2_priv)) {
601 		wpa_printf(MSG_INFO,
602 			   "EAP-TEAP: Phase 2 key material not available");
603 		return -1;
604 	}
605 
606 	if (data->phase2_method->isKeyAvailable &&
607 	    data->phase2_method->getKey) {
608 		msk = data->phase2_method->getKey(sm, data->phase2_priv,
609 						  &msk_len);
610 		if (!msk) {
611 			wpa_printf(MSG_INFO,
612 				   "EAP-TEAP: Could not fetch Phase 2 MSK");
613 			return -1;
614 		}
615 	}
616 
617 	if (data->phase2_method->isKeyAvailable &&
618 	    data->phase2_method->get_emsk) {
619 		emsk = data->phase2_method->get_emsk(sm, data->phase2_priv,
620 						     &emsk_len);
621 	}
622 
623 out:
624 	if (data->teap_compat == TEAP_FREERADIUS) {
625 		u8 tmp_simck[EAP_TEAP_SIMCK_LEN];
626 		u8 tmp_cmk[EAP_TEAP_CMK_LEN];
627 
628 		wpa_printf(MSG_DEBUG,
629 			   "EAP-TEAP: FreeRADIUS compatibility: use S-IMCK_MSK[j-1] and S-IMCK_EMSK[j-1] based on MSK/EMSK derivations instead of a single selected S-IMCK[j-1]");
630 		res = eap_teap_derive_imck(data->tls_cs, data->simck_msk,
631 					   msk, msk_len, emsk, emsk_len,
632 					   data->simck_msk, cmk_msk,
633 					   tmp_simck, tmp_cmk);
634 		if (emsk)
635 			res = eap_teap_derive_imck(data->tls_cs,
636 						   data->simck_emsk,
637 						   msk, msk_len, emsk, emsk_len,
638 						   tmp_simck, tmp_cmk,
639 						   data->simck_emsk, cmk_emsk);
640 	} else {
641 		res = eap_teap_derive_imck(data->tls_cs, data->simck,
642 					   msk, msk_len, emsk, emsk_len,
643 					   data->simck_msk, cmk_msk,
644 					   data->simck_emsk, cmk_emsk);
645 	}
646 	bin_clear_free(msk, msk_len);
647 	bin_clear_free(emsk, emsk_len);
648 	if (res == 0) {
649 		data->simck_idx++;
650 		data->cmk_emsk_available = emsk != NULL;
651 	}
652 	return res;
653 }
654 
655 
eap_teap_session_id(struct eap_teap_data * data)656 static int eap_teap_session_id(struct eap_teap_data *data)
657 {
658 	const size_t max_id_len = 100;
659 	int res;
660 
661 	os_free(data->session_id);
662 	data->session_id = os_malloc(max_id_len);
663 	if (!data->session_id)
664 		return -1;
665 
666 	data->session_id[0] = EAP_TYPE_TEAP;
667 	res = tls_get_tls_unique(data->ssl.conn, data->session_id + 1,
668 				 max_id_len - 1);
669 	if (res < 0 || (size_t) res >= max_id_len) {
670 		os_free(data->session_id);
671 		data->session_id = NULL;
672 		wpa_printf(MSG_ERROR, "EAP-TEAP: Failed to derive Session-Id");
673 		return -1;
674 	}
675 
676 	data->id_len = 1 + res;
677 	wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Derived Session-Id",
678 		    data->session_id, data->id_len);
679 	return 0;
680 }
681 
682 
eap_teap_process_crypto_binding(struct eap_sm * sm,struct eap_teap_data * data,struct eap_method_ret * ret,const struct teap_tlv_crypto_binding * cb,size_t bind_len)683 static struct wpabuf * eap_teap_process_crypto_binding(
684 	struct eap_sm *sm, struct eap_teap_data *data,
685 	struct eap_method_ret *ret,
686 	const struct teap_tlv_crypto_binding *cb, size_t bind_len)
687 {
688 	struct wpabuf *resp;
689 	u8 *pos;
690 	u8 cmk_msk[EAP_TEAP_CMK_LEN];
691 	u8 cmk_emsk[EAP_TEAP_CMK_LEN];
692 	const u8 *cmk_msk_ptr = NULL;
693 	const u8 *cmk_emsk_ptr = NULL;
694 	int res;
695 	size_t len;
696 	u8 flags;
697 	bool server_msk, server_emsk;
698 
699 	if (eap_teap_validate_crypto_binding(data, cb) < 0 ||
700 	    eap_teap_get_cmk(sm, data, cmk_msk, cmk_emsk) < 0)
701 		return NULL;
702 
703 	/* Validate received MSK/EMSK Compound MAC */
704 	flags = cb->subtype >> 4;
705 	server_msk = flags == TEAP_CRYPTO_BINDING_MSK_CMAC ||
706 		flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC;
707 	server_emsk = flags == TEAP_CRYPTO_BINDING_EMSK_CMAC ||
708 		flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC;
709 
710 	if (server_msk) {
711 		u8 msk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
712 
713 		if (eap_teap_compound_mac(data->tls_cs, cb,
714 					  data->server_outer_tlvs,
715 					  data->peer_outer_tlvs, cmk_msk,
716 					  msk_compound_mac) < 0)
717 			return NULL;
718 		res = os_memcmp_const(msk_compound_mac, cb->msk_compound_mac,
719 				      EAP_TEAP_COMPOUND_MAC_LEN);
720 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received MSK Compound MAC",
721 			    cb->msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
722 		wpa_hexdump(MSG_MSGDUMP,
723 			    "EAP-TEAP: Calculated MSK Compound MAC",
724 			    msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
725 		if (res != 0) {
726 			wpa_printf(MSG_INFO,
727 				   "EAP-TEAP: MSK Compound MAC did not match");
728 			return NULL;
729 		}
730 	}
731 
732 	if (server_emsk && data->cmk_emsk_available) {
733 		u8 emsk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
734 
735 		if (eap_teap_compound_mac(data->tls_cs, cb,
736 					  data->server_outer_tlvs,
737 					  data->peer_outer_tlvs, cmk_emsk,
738 					  emsk_compound_mac) < 0)
739 			return NULL;
740 		res = os_memcmp_const(emsk_compound_mac, cb->emsk_compound_mac,
741 				      EAP_TEAP_COMPOUND_MAC_LEN);
742 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received EMSK Compound MAC",
743 			    cb->emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
744 		wpa_hexdump(MSG_MSGDUMP,
745 			    "EAP-TEAP: Calculated EMSK Compound MAC",
746 			    emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
747 		if (res != 0) {
748 			wpa_printf(MSG_INFO,
749 				   "EAP-TEAP: EMSK Compound MAC did not match");
750 			return NULL;
751 		}
752 	}
753 
754 	if (flags == TEAP_CRYPTO_BINDING_EMSK_CMAC &&
755 	    !data->cmk_emsk_available) {
756 		wpa_printf(MSG_INFO,
757 			   "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
758 		return NULL;
759 	}
760 
761 	/*
762 	 * Compound MAC was valid, so authentication succeeded. Reply with
763 	 * crypto binding to allow server to complete authentication.
764 	 */
765 
766 	if (server_emsk && data->cmk_emsk_available) {
767 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Selected S-IMCK_EMSK");
768 		os_memcpy(data->simck, data->simck_emsk, EAP_TEAP_SIMCK_LEN);
769 		cmk_emsk_ptr = cmk_emsk;
770 	} else if (server_msk) {
771 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Selected S-IMCK_MSK");
772 		os_memcpy(data->simck, data->simck_msk, EAP_TEAP_SIMCK_LEN);
773 		cmk_msk_ptr = cmk_msk;
774 	} else {
775 		return NULL;
776 	}
777 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Selected S-IMCK[j]",
778 			data->simck, EAP_TEAP_SIMCK_LEN);
779 
780 	len = sizeof(struct teap_tlv_crypto_binding);
781 	resp = wpabuf_alloc(len);
782 	if (!resp)
783 		return NULL;
784 
785 	if (data->phase2_success && eap_teap_derive_msk(data) < 0) {
786 		wpa_printf(MSG_INFO, "EAP-TEAP: Failed to generate MSK");
787 		ret->methodState = METHOD_DONE;
788 		ret->decision = DECISION_FAIL;
789 		data->phase2_success = 0;
790 		wpabuf_free(resp);
791 		return NULL;
792 	}
793 
794 	if (data->phase2_success && eap_teap_session_id(data) < 0) {
795 		wpabuf_free(resp);
796 		return NULL;
797 	}
798 
799 	pos = wpabuf_put(resp, sizeof(struct teap_tlv_crypto_binding));
800 	if (eap_teap_write_crypto_binding(
801 		    data, (struct teap_tlv_crypto_binding *) pos,
802 		    cb, cmk_msk_ptr, cmk_emsk_ptr) < 0) {
803 		wpabuf_free(resp);
804 		return NULL;
805 	}
806 
807 	return resp;
808 }
809 
810 
eap_teap_parse_decrypted(struct wpabuf * decrypted,struct eap_teap_tlv_parse * tlv,struct wpabuf ** resp)811 static int eap_teap_parse_decrypted(struct wpabuf *decrypted,
812 				    struct eap_teap_tlv_parse *tlv,
813 				    struct wpabuf **resp)
814 {
815 	u16 tlv_type;
816 	int mandatory, res;
817 	size_t len;
818 	u8 *pos, *end;
819 
820 	os_memset(tlv, 0, sizeof(*tlv));
821 
822 	/* Parse TLVs from the decrypted Phase 2 data */
823 	pos = wpabuf_mhead(decrypted);
824 	end = pos + wpabuf_len(decrypted);
825 	while (end - pos >= 4) {
826 		mandatory = pos[0] & 0x80;
827 		tlv_type = WPA_GET_BE16(pos) & 0x3fff;
828 		pos += 2;
829 		len = WPA_GET_BE16(pos);
830 		pos += 2;
831 		if (len > (size_t) (end - pos)) {
832 			wpa_printf(MSG_INFO, "EAP-TEAP: TLV overflow");
833 			return -1;
834 		}
835 		wpa_printf(MSG_DEBUG,
836 			   "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
837 			   tlv_type, eap_teap_tlv_type_str(tlv_type),
838 			   (unsigned int) len,
839 			   mandatory ? " (mandatory)" : "");
840 
841 		res = eap_teap_parse_tlv(tlv, tlv_type, pos, len);
842 		if (res == -2)
843 			break;
844 		if (res < 0) {
845 			if (mandatory) {
846 				wpa_printf(MSG_DEBUG,
847 					   "EAP-TEAP: NAK unknown mandatory TLV type %u",
848 					   tlv_type);
849 				*resp = eap_teap_tlv_nak(0, tlv_type);
850 				break;
851 			}
852 
853 			wpa_printf(MSG_DEBUG,
854 				   "EAP-TEAP: Ignore unknown optional TLV type %u",
855 				   tlv_type);
856 		}
857 
858 		pos += len;
859 	}
860 
861 	return 0;
862 }
863 
864 
eap_teap_process_decrypted(struct eap_sm * sm,struct eap_teap_data * data,struct eap_method_ret * ret,u8 identifier,struct wpabuf * decrypted,struct wpabuf ** out_data)865 static int eap_teap_process_decrypted(struct eap_sm *sm,
866 				      struct eap_teap_data *data,
867 				      struct eap_method_ret *ret,
868 				      u8 identifier,
869 				      struct wpabuf *decrypted,
870 				      struct wpabuf **out_data)
871 {
872 	struct wpabuf *resp = NULL, *tmp;
873 	struct eap_teap_tlv_parse tlv;
874 	int failed = 0;
875 	enum teap_error_codes error = 0;
876 	int iresult_added = 0;
877 
878 	if (eap_teap_parse_decrypted(decrypted, &tlv, &resp) < 0) {
879 		/* Parsing failed - no response available */
880 		return 0;
881 	}
882 
883 	if (resp) {
884 		/* Parsing rejected the message - send out an error response */
885 		goto send_resp;
886 	}
887 
888 	if (tlv.result == TEAP_STATUS_FAILURE) {
889 		/* Server indicated failure - respond similarly per
890 		 * RFC 7170, 3.6.3. This authentication exchange cannot succeed
891 		 * and will be terminated with a cleartext EAP Failure. */
892 		wpa_printf(MSG_DEBUG,
893 			   "EAP-TEAP: Server rejected authentication");
894 		resp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
895 		ret->methodState = METHOD_DONE;
896 		ret->decision = DECISION_FAIL;
897 		goto send_resp;
898 	}
899 
900 	if (tlv.iresult == TEAP_STATUS_SUCCESS && !tlv.crypto_binding) {
901 		/* Intermediate-Result TLV indicating success, but no
902 		 * Crypto-Binding TLV */
903 		wpa_printf(MSG_DEBUG,
904 			   "EAP-TEAP: Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
905 		failed = 1;
906 		error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
907 		goto done;
908 	}
909 
910 	if (!data->iresult_verified && !data->result_success_done &&
911 	    tlv.result == TEAP_STATUS_SUCCESS && !tlv.crypto_binding) {
912 		/* Result TLV indicating success, but no Crypto-Binding TLV */
913 		wpa_printf(MSG_DEBUG,
914 			   "EAP-TEAP: Result TLV indicating success, but no Crypto-Binding TLV");
915 		failed = 1;
916 		error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
917 		goto done;
918 	}
919 
920 	if (tlv.iresult != TEAP_STATUS_SUCCESS &&
921 	    tlv.iresult != TEAP_STATUS_FAILURE &&
922 	    data->inner_method_done) {
923 		wpa_printf(MSG_DEBUG,
924 			   "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
925 		failed = 1;
926 		error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
927 		goto done;
928 	}
929 
930 	if (tlv.crypto_binding) {
931 		if (tlv.iresult != TEAP_STATUS_SUCCESS &&
932 		    tlv.result != TEAP_STATUS_SUCCESS) {
933 			wpa_printf(MSG_DEBUG,
934 				   "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
935 			failed = 1;
936 			error = TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED;
937 			goto done;
938 		}
939 
940 		tmp = eap_teap_process_crypto_binding(sm, data, ret,
941 						      tlv.crypto_binding,
942 						      tlv.crypto_binding_len);
943 		if (!tmp) {
944 			failed = 1;
945 			error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
946 		} else {
947 			resp = wpabuf_concat(resp, tmp);
948 			if (tlv.result == TEAP_STATUS_SUCCESS && !failed)
949 				data->result_success_done = 1;
950 			if (tlv.iresult == TEAP_STATUS_SUCCESS && !failed) {
951 				data->inner_method_done = 0;
952 				data->iresult_verified = 1;
953 			}
954 		}
955 	}
956 
957 	if (tlv.identity_type == TEAP_IDENTITY_TYPE_MACHINE) {
958 		struct eap_peer_config *config = eap_get_config(sm);
959 
960 		sm->use_machine_cred = config && config->machine_identity &&
961 			config->machine_identity_len;
962 	} else if (tlv.identity_type) {
963 		sm->use_machine_cred = 0;
964 	}
965 	if (tlv.identity_type) {
966 		struct eap_peer_config *config = eap_get_config(sm);
967 
968 		os_free(data->phase2_types);
969 		data->phase2_types = NULL;
970 		data->num_phase2_types = 0;
971 		if (config &&
972 		    eap_peer_select_phase2_methods(config, "auth=",
973 						   &data->phase2_types,
974 						   &data->num_phase2_types,
975 						   sm->use_machine_cred) < 0) {
976 			wpa_printf(MSG_INFO,
977 				   "EAP-TEAP: Failed to update Phase 2 EAP types");
978 			failed = 1;
979 			goto done;
980 		}
981 	}
982 
983 	if (tlv.basic_auth_req) {
984 		tmp = eap_teap_process_basic_auth_req(sm, data,
985 						      tlv.basic_auth_req,
986 						      tlv.basic_auth_req_len,
987 						      tlv.identity_type);
988 		if (!tmp)
989 			failed = 1;
990 		resp = wpabuf_concat(resp, tmp);
991 	} else if (tlv.eap_payload_tlv) {
992 		tmp = eap_teap_process_eap_payload_tlv(sm, data, ret,
993 						       tlv.eap_payload_tlv,
994 						       tlv.eap_payload_tlv_len,
995 						       tlv.identity_type);
996 		if (!tmp)
997 			failed = 1;
998 		resp = wpabuf_concat(resp, tmp);
999 
1000 		if (tlv.iresult == TEAP_STATUS_SUCCESS ||
1001 		    tlv.iresult == TEAP_STATUS_FAILURE) {
1002 			tmp = eap_teap_tlv_result(failed ?
1003 						  TEAP_STATUS_FAILURE :
1004 						  TEAP_STATUS_SUCCESS, 1);
1005 			resp = wpabuf_concat(resp, tmp);
1006 			if (tlv.iresult == TEAP_STATUS_FAILURE)
1007 				failed = 1;
1008 			iresult_added = 1;
1009 		}
1010 	}
1011 
1012 	if (data->result_success_done &&
1013 	    tls_connection_get_own_cert_used(data->ssl.conn) &&
1014 	    eap_teap_derive_msk(data) == 0) {
1015 		/* Assume the server might accept authentication without going
1016 		 * through inner authentication. */
1017 		wpa_printf(MSG_DEBUG,
1018 			   "EAP-TEAP: Client certificate used - server may decide to skip inner authentication");
1019 		ret->methodState = METHOD_MAY_CONT;
1020 		ret->decision = DECISION_COND_SUCC;
1021 	}
1022 
1023 done:
1024 	if (failed) {
1025 		tmp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
1026 		resp = wpabuf_concat(tmp, resp);
1027 
1028 		if (error != 0) {
1029 			tmp = eap_teap_tlv_error(error);
1030 			resp = wpabuf_concat(tmp, resp);
1031 		}
1032 
1033 		ret->methodState = METHOD_DONE;
1034 		ret->decision = DECISION_FAIL;
1035 	} else if (tlv.result == TEAP_STATUS_SUCCESS) {
1036 		tmp = eap_teap_tlv_result(TEAP_STATUS_SUCCESS, 0);
1037 		resp = wpabuf_concat(tmp, resp);
1038 	}
1039 	if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
1040 	     tlv.iresult == TEAP_STATUS_FAILURE) && !iresult_added) {
1041 		tmp = eap_teap_tlv_result((!failed && data->phase2_success) ?
1042 					  TEAP_STATUS_SUCCESS :
1043 					  TEAP_STATUS_FAILURE, 1);
1044 		resp = wpabuf_concat(tmp, resp);
1045 	}
1046 
1047 	if (resp && tlv.result == TEAP_STATUS_SUCCESS && !failed &&
1048 	    (tlv.crypto_binding || data->iresult_verified) &&
1049 	    data->phase2_success) {
1050 		/* Successfully completed Phase 2 */
1051 		wpa_printf(MSG_DEBUG,
1052 			   "EAP-TEAP: Authentication completed successfully");
1053 		ret->methodState = METHOD_MAY_CONT;
1054 		data->on_tx_completion = METHOD_DONE;
1055 		ret->decision = DECISION_UNCOND_SUCC;
1056 	}
1057 
1058 	if (!resp) {
1059 		wpa_printf(MSG_DEBUG,
1060 			   "EAP-TEAP: No recognized TLVs - send empty response packet");
1061 		resp = wpabuf_alloc(1);
1062 	}
1063 
1064 send_resp:
1065 	if (!resp)
1066 		return 0;
1067 
1068 	wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: Encrypting Phase 2 data", resp);
1069 	if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
1070 				 data->teap_version, identifier,
1071 				 resp, out_data)) {
1072 		wpa_printf(MSG_INFO,
1073 			   "EAP-TEAP: Failed to encrypt a Phase 2 frame");
1074 	}
1075 	wpabuf_free(resp);
1076 
1077 	return 0;
1078 }
1079 
1080 
eap_teap_decrypt(struct eap_sm * sm,struct eap_teap_data * data,struct eap_method_ret * ret,u8 identifier,const struct wpabuf * in_data,struct wpabuf ** out_data)1081 static int eap_teap_decrypt(struct eap_sm *sm, struct eap_teap_data *data,
1082 			    struct eap_method_ret *ret, u8 identifier,
1083 			    const struct wpabuf *in_data,
1084 			    struct wpabuf **out_data)
1085 {
1086 	struct wpabuf *in_decrypted;
1087 	int res;
1088 
1089 	wpa_printf(MSG_DEBUG,
1090 		   "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1091 		   (unsigned long) wpabuf_len(in_data));
1092 
1093 	if (data->pending_phase2_req) {
1094 		wpa_printf(MSG_DEBUG,
1095 			   "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
1096 		/* Clear TLS reassembly state. */
1097 		eap_peer_tls_reset_input(&data->ssl);
1098 
1099 		in_decrypted = data->pending_phase2_req;
1100 		data->pending_phase2_req = NULL;
1101 		goto continue_req;
1102 	}
1103 
1104 	if (wpabuf_len(in_data) == 0) {
1105 		/* Received TLS ACK - requesting more fragments */
1106 		res = eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
1107 					   data->teap_version,
1108 					   identifier, NULL, out_data);
1109 		if (res == 0 && !data->ssl.tls_out &&
1110 		    data->on_tx_completion) {
1111 			wpa_printf(MSG_DEBUG,
1112 				   "EAP-TEAP: Mark authentication completed at full TX of fragments");
1113 			ret->methodState = data->on_tx_completion;
1114 			data->on_tx_completion = 0;
1115 			ret->decision = DECISION_UNCOND_SUCC;
1116 		}
1117 		return res;
1118 	}
1119 
1120 	res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
1121 	if (res)
1122 		return res;
1123 
1124 continue_req:
1125 	wpa_hexdump_buf(MSG_MSGDUMP, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
1126 			in_decrypted);
1127 
1128 	if (wpabuf_len(in_decrypted) < 4) {
1129 		wpa_printf(MSG_INFO,
1130 			   "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
1131 			   (unsigned long) wpabuf_len(in_decrypted));
1132 		wpabuf_free(in_decrypted);
1133 		return -1;
1134 	}
1135 
1136 	res = eap_teap_process_decrypted(sm, data, ret, identifier,
1137 					 in_decrypted, out_data);
1138 
1139 	wpabuf_free(in_decrypted);
1140 
1141 	return res;
1142 }
1143 
1144 
eap_teap_process_start(struct eap_sm * sm,struct eap_teap_data * data,u8 flags,const u8 * pos,size_t left)1145 static int eap_teap_process_start(struct eap_sm *sm,
1146 				  struct eap_teap_data *data, u8 flags,
1147 				  const u8 *pos, size_t left)
1148 {
1149 	const u8 *a_id = NULL;
1150 
1151 	/* TODO: Support (mostly theoretical) case of TEAP/Start request being
1152 	 * fragmented */
1153 
1154 	/* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
1155 	data->received_version = flags & EAP_TLS_VERSION_MASK;
1156 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
1157 		   data->received_version, data->teap_version);
1158 	if (data->received_version < 1) {
1159 		/* Version 1 was the first defined version, so reject 0 */
1160 		wpa_printf(MSG_INFO,
1161 			   "EAP-TEAP: Server used unknown TEAP version %u",
1162 			   data->received_version);
1163 		return -1;
1164 	}
1165 	if (data->received_version < data->teap_version)
1166 		data->teap_version = data->received_version;
1167 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Using TEAP version %d",
1168 		   data->teap_version);
1169 	wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message payload", pos, left);
1170 
1171 	/* Parse Authority-ID TLV from Outer TLVs, if present */
1172 	if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
1173 		const u8 *outer_pos, *outer_end;
1174 		u32 outer_tlv_len;
1175 
1176 		if (left < 4) {
1177 			wpa_printf(MSG_INFO,
1178 				   "EAP-TEAP: Not enough room for the Outer TLV Length field");
1179 			return -1;
1180 		}
1181 
1182 		outer_tlv_len = WPA_GET_BE32(pos);
1183 		pos += 4;
1184 		left -= 4;
1185 
1186 		if (outer_tlv_len > left) {
1187 			wpa_printf(MSG_INFO,
1188 				   "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
1189 				   outer_tlv_len, (unsigned int) left);
1190 			return -1;
1191 		}
1192 
1193 		outer_pos = pos + left - outer_tlv_len;
1194 		outer_end = outer_pos + outer_tlv_len;
1195 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message Outer TLVs",
1196 			    outer_pos, outer_tlv_len);
1197 		wpabuf_free(data->server_outer_tlvs);
1198 		data->server_outer_tlvs = wpabuf_alloc_copy(outer_pos,
1199 							    outer_tlv_len);
1200 		if (!data->server_outer_tlvs)
1201 			return -1;
1202 		left -= outer_tlv_len;
1203 		if (left > 0) {
1204 			wpa_hexdump(MSG_INFO,
1205 				    "EAP-TEAP: Unexpected TLS Data in Start message",
1206 				    pos, left);
1207 			return -1;
1208 		}
1209 
1210 		while (outer_pos < outer_end) {
1211 			u16 tlv_type, tlv_len;
1212 
1213 			if (outer_end - outer_pos < 4) {
1214 				wpa_printf(MSG_INFO,
1215 					   "EAP-TEAP: Truncated Outer TLV header");
1216 				return -1;
1217 			}
1218 			tlv_type = WPA_GET_BE16(outer_pos);
1219 			outer_pos += 2;
1220 			tlv_len = WPA_GET_BE16(outer_pos);
1221 			outer_pos += 2;
1222 			/* Outer TLVs are required to be optional, so no need to
1223 			 * check the M flag */
1224 			tlv_type &= TEAP_TLV_TYPE_MASK;
1225 			wpa_printf(MSG_DEBUG,
1226 				   "EAP-TEAP: Outer TLV: Type=%u Length=%u",
1227 				   tlv_type, tlv_len);
1228 			if (outer_end - outer_pos < tlv_len) {
1229 				wpa_printf(MSG_INFO,
1230 					   "EAP-TEAP: Truncated Outer TLV (Type %u)",
1231 					   tlv_type);
1232 				return -1;
1233 			}
1234 			if (tlv_type == TEAP_TLV_AUTHORITY_ID) {
1235 				wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Authority-ID",
1236 					    outer_pos, tlv_len);
1237 				if (a_id) {
1238 					wpa_printf(MSG_INFO,
1239 						   "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
1240 					return -1;
1241 				}
1242 				a_id = outer_pos;
1243 			} else {
1244 				wpa_printf(MSG_DEBUG,
1245 					   "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
1246 					   tlv_type);
1247 			}
1248 			outer_pos += tlv_len;
1249 		}
1250 	} else if (left > 0) {
1251 		wpa_hexdump(MSG_INFO,
1252 			    "EAP-TEAP: Unexpected TLS Data in Start message",
1253 			    pos, left);
1254 		return -1;
1255 	}
1256 
1257 	return 0;
1258 }
1259 
1260 
1261 #ifdef CONFIG_TESTING_OPTIONS
eap_teap_add_stub_outer_tlvs(struct eap_teap_data * data,struct wpabuf * resp)1262 static struct wpabuf * eap_teap_add_stub_outer_tlvs(struct eap_teap_data *data,
1263 						    struct wpabuf *resp)
1264 {
1265 	struct wpabuf *resp2;
1266 	u16 len;
1267 	const u8 *pos;
1268 	u8 flags;
1269 
1270 	wpabuf_free(data->peer_outer_tlvs);
1271 	data->peer_outer_tlvs = wpabuf_alloc(4 + 4);
1272 	if (!data->peer_outer_tlvs) {
1273 		wpabuf_free(resp);
1274 		return NULL;
1275 	}
1276 
1277 	/* Outer TLVs (stub Vendor-Specific TLV for testing) */
1278 	wpabuf_put_be16(data->peer_outer_tlvs, TEAP_TLV_VENDOR_SPECIFIC);
1279 	wpabuf_put_be16(data->peer_outer_tlvs, 4);
1280 	wpabuf_put_be32(data->peer_outer_tlvs, EAP_VENDOR_HOSTAP);
1281 	wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: TESTING - Add stub Outer TLVs",
1282 			data->peer_outer_tlvs);
1283 
1284 	wpa_hexdump_buf(MSG_DEBUG,
1285 			"EAP-TEAP: TEAP/Start response before modification",
1286 			resp);
1287 	resp2 = wpabuf_alloc(wpabuf_len(resp) + 4 +
1288 			     wpabuf_len(data->peer_outer_tlvs));
1289 	if (!resp2) {
1290 		wpabuf_free(resp);
1291 		return NULL;
1292 	}
1293 
1294 	pos = wpabuf_head(resp);
1295 	wpabuf_put_u8(resp2, *pos++); /* Code */
1296 	wpabuf_put_u8(resp2, *pos++); /* Identifier */
1297 	len = WPA_GET_BE16(pos);
1298 	pos += 2;
1299 	wpabuf_put_be16(resp2, len + 4 + wpabuf_len(data->peer_outer_tlvs));
1300 	wpabuf_put_u8(resp2, *pos++); /* Type */
1301 	/* Flags | Ver (with Outer TLV length included flag set to 1) */
1302 	flags = *pos++;
1303 	if (flags & (EAP_TEAP_FLAGS_OUTER_TLV_LEN |
1304 		     EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
1305 		wpa_printf(MSG_INFO,
1306 			   "EAP-TEAP: Cannot add Outer TLVs for testing");
1307 		wpabuf_free(resp);
1308 		wpabuf_free(resp2);
1309 		return NULL;
1310 	}
1311 	flags |= EAP_TEAP_FLAGS_OUTER_TLV_LEN;
1312 	wpabuf_put_u8(resp2, flags);
1313 	/* Outer TLV Length */
1314 	wpabuf_put_be32(resp2, wpabuf_len(data->peer_outer_tlvs));
1315 	/* TLS Data */
1316 	wpabuf_put_data(resp2, pos, wpabuf_len(resp) - 6);
1317 	wpabuf_put_buf(resp2, data->peer_outer_tlvs); /* Outer TLVs */
1318 
1319 	wpabuf_free(resp);
1320 	wpa_hexdump_buf(MSG_DEBUG,
1321 			"EAP-TEAP: TEAP/Start response after modification",
1322 			resp2);
1323 	return resp2;
1324 }
1325 #endif /* CONFIG_TESTING_OPTIONS */
1326 
1327 
eap_teap_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)1328 static struct wpabuf * eap_teap_process(struct eap_sm *sm, void *priv,
1329 					struct eap_method_ret *ret,
1330 					const struct wpabuf *reqData)
1331 {
1332 	const struct eap_hdr *req;
1333 	size_t left;
1334 	int res;
1335 	u8 flags, id;
1336 	struct wpabuf *resp;
1337 	const u8 *pos;
1338 	struct eap_teap_data *data = priv;
1339 	struct wpabuf msg;
1340 
1341 	pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TEAP, ret,
1342 					reqData, &left, &flags);
1343 	if (!pos)
1344 		return NULL;
1345 
1346 	req = wpabuf_head(reqData);
1347 	id = req->identifier;
1348 
1349 	if (flags & EAP_TLS_FLAGS_START) {
1350 		if (eap_teap_process_start(sm, data, flags, pos, left) < 0)
1351 			return NULL;
1352 
1353 		/* Outer TLVs are not used in further packet processing and
1354 		 * there cannot be TLS Data in this TEAP/Start message, so
1355 		 * enforce that by ignoring whatever data might remain in the
1356 		 * buffer. */
1357 		left = 0;
1358 	} else if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
1359 		/* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
1360 		 * Outer TLVs MUST be ignored instead of ignoring the full
1361 		 * message. */
1362 		wpa_printf(MSG_INFO,
1363 			   "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
1364 		return NULL;
1365 	}
1366 
1367 	wpabuf_set(&msg, pos, left);
1368 
1369 	resp = NULL;
1370 	if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1371 	    !data->resuming) {
1372 		/* Process tunneled (encrypted) phase 2 data. */
1373 		res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
1374 		if (res < 0) {
1375 			ret->methodState = METHOD_DONE;
1376 			ret->decision = DECISION_FAIL;
1377 			/*
1378 			 * Ack possible Alert that may have caused failure in
1379 			 * decryption.
1380 			 */
1381 			res = 1;
1382 		}
1383 	} else {
1384 		if (sm->waiting_ext_cert_check && data->pending_resp) {
1385 			struct eap_peer_config *config = eap_get_config(sm);
1386 
1387 			if (config->pending_ext_cert_check ==
1388 			    EXT_CERT_CHECK_GOOD) {
1389 				wpa_printf(MSG_DEBUG,
1390 					   "EAP-TEAP: External certificate check succeeded - continue handshake");
1391 				resp = data->pending_resp;
1392 				data->pending_resp = NULL;
1393 				sm->waiting_ext_cert_check = 0;
1394 				return resp;
1395 			}
1396 
1397 			if (config->pending_ext_cert_check ==
1398 			    EXT_CERT_CHECK_BAD) {
1399 				wpa_printf(MSG_DEBUG,
1400 					   "EAP-TEAP: External certificate check failed - force authentication failure");
1401 				ret->methodState = METHOD_DONE;
1402 				ret->decision = DECISION_FAIL;
1403 				sm->waiting_ext_cert_check = 0;
1404 				return NULL;
1405 			}
1406 
1407 			wpa_printf(MSG_DEBUG,
1408 				   "EAP-TEAP: Continuing to wait external server certificate validation");
1409 			return NULL;
1410 		}
1411 
1412 		/* Continue processing TLS handshake (phase 1). */
1413 		res = eap_peer_tls_process_helper(sm, &data->ssl,
1414 						  EAP_TYPE_TEAP,
1415 						  data->teap_version, id, &msg,
1416 						  &resp);
1417 		if (res < 0) {
1418 			wpa_printf(MSG_DEBUG,
1419 				   "EAP-TEAP: TLS processing failed");
1420 			ret->methodState = METHOD_DONE;
1421 			ret->decision = DECISION_FAIL;
1422 			return resp;
1423 		}
1424 
1425 		if (sm->waiting_ext_cert_check) {
1426 			wpa_printf(MSG_DEBUG,
1427 				   "EAP-TEAP: Waiting external server certificate validation");
1428 			wpabuf_free(data->pending_resp);
1429 			data->pending_resp = resp;
1430 			return NULL;
1431 		}
1432 
1433 		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1434 			wpa_printf(MSG_DEBUG,
1435 				   "EAP-TEAP: TLS done, proceed to Phase 2");
1436 			data->tls_cs =
1437 				tls_connection_get_cipher_suite(data->ssl.conn);
1438 			wpa_printf(MSG_DEBUG,
1439 				   "EAP-TEAP: TLS cipher suite 0x%04x",
1440 				   data->tls_cs);
1441 
1442 			data->resuming = 0;
1443 			if (eap_teap_derive_key_auth(sm, data) < 0) {
1444 				wpa_printf(MSG_DEBUG,
1445 					   "EAP-TEAP: Could not derive keys");
1446 				ret->methodState = METHOD_DONE;
1447 				ret->decision = DECISION_FAIL;
1448 				wpabuf_free(resp);
1449 				return NULL;
1450 			}
1451 		}
1452 
1453 		if (res == 2) {
1454 			/*
1455 			 * Application data included in the handshake message.
1456 			 */
1457 			wpabuf_free(data->pending_phase2_req);
1458 			data->pending_phase2_req = resp;
1459 			resp = NULL;
1460 			res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
1461 		}
1462 	}
1463 
1464 	if (res == 1) {
1465 		wpabuf_free(resp);
1466 		return eap_peer_tls_build_ack(id, EAP_TYPE_TEAP,
1467 					      data->teap_version);
1468 	}
1469 
1470 #ifdef CONFIG_TESTING_OPTIONS
1471 	if (data->test_outer_tlvs && res == 0 && resp &&
1472 	    (flags & EAP_TLS_FLAGS_START) && wpabuf_len(resp) >= 6)
1473 		resp = eap_teap_add_stub_outer_tlvs(data, resp);
1474 #endif /* CONFIG_TESTING_OPTIONS */
1475 
1476 	return resp;
1477 }
1478 
1479 
1480 #if 0 /* TODO */
1481 static bool eap_teap_has_reauth_data(struct eap_sm *sm, void *priv)
1482 {
1483 	struct eap_teap_data *data = priv;
1484 
1485 	return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
1486 }
1487 
1488 
1489 static void eap_teap_deinit_for_reauth(struct eap_sm *sm, void *priv)
1490 {
1491 	struct eap_teap_data *data = priv;
1492 
1493 	if (data->phase2_priv && data->phase2_method &&
1494 	    data->phase2_method->deinit_for_reauth)
1495 		data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
1496 	eap_teap_clear(data);
1497 }
1498 
1499 
1500 static void * eap_teap_init_for_reauth(struct eap_sm *sm, void *priv)
1501 {
1502 	struct eap_teap_data *data = priv;
1503 
1504 	if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1505 		eap_teap_deinit(sm, data);
1506 		return NULL;
1507 	}
1508 	if (data->phase2_priv && data->phase2_method &&
1509 	    data->phase2_method->init_for_reauth)
1510 		data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1511 	data->phase2_success = 0;
1512 	data->inner_method_done = 0;
1513 	data->result_success_done = 0;
1514 	data->iresult_verified = 0;
1515 	data->done_on_tx_completion = 0;
1516 	data->resuming = 1;
1517 	data->simck_idx = 0;
1518 	return priv;
1519 }
1520 #endif
1521 
1522 
eap_teap_get_status(struct eap_sm * sm,void * priv,char * buf,size_t buflen,int verbose)1523 static int eap_teap_get_status(struct eap_sm *sm, void *priv, char *buf,
1524 			       size_t buflen, int verbose)
1525 {
1526 	struct eap_teap_data *data = priv;
1527 	int len, ret;
1528 
1529 	len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1530 	if (data->phase2_method) {
1531 		ret = os_snprintf(buf + len, buflen - len,
1532 				  "EAP-TEAP Phase 2 method=%s\n",
1533 				  data->phase2_method->name);
1534 		if (os_snprintf_error(buflen - len, ret))
1535 			return len;
1536 		len += ret;
1537 	}
1538 	return len;
1539 }
1540 
1541 
eap_teap_isKeyAvailable(struct eap_sm * sm,void * priv)1542 static bool eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv)
1543 {
1544 	struct eap_teap_data *data = priv;
1545 
1546 	return data->success;
1547 }
1548 
1549 
eap_teap_getKey(struct eap_sm * sm,void * priv,size_t * len)1550 static u8 * eap_teap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1551 {
1552 	struct eap_teap_data *data = priv;
1553 	u8 *key;
1554 
1555 	if (!data->success)
1556 		return NULL;
1557 
1558 	key = os_memdup(data->key_data, EAP_TEAP_KEY_LEN);
1559 	if (!key)
1560 		return NULL;
1561 
1562 	*len = EAP_TEAP_KEY_LEN;
1563 
1564 	return key;
1565 }
1566 
1567 
eap_teap_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1568 static u8 * eap_teap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1569 {
1570 	struct eap_teap_data *data = priv;
1571 	u8 *id;
1572 
1573 	if (!data->success || !data->session_id)
1574 		return NULL;
1575 
1576 	id = os_memdup(data->session_id, data->id_len);
1577 	if (!id)
1578 		return NULL;
1579 
1580 	*len = data->id_len;
1581 
1582 	return id;
1583 }
1584 
1585 
eap_teap_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1586 static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1587 {
1588 	struct eap_teap_data *data = priv;
1589 	u8 *key;
1590 
1591 	if (!data->success)
1592 		return NULL;
1593 
1594 	key = os_memdup(data->emsk, EAP_EMSK_LEN);
1595 	if (!key)
1596 		return NULL;
1597 
1598 	*len = EAP_EMSK_LEN;
1599 
1600 	return key;
1601 }
1602 
1603 
eap_peer_teap_register(void)1604 int eap_peer_teap_register(void)
1605 {
1606 	struct eap_method *eap;
1607 
1608 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1609 				    EAP_VENDOR_IETF, EAP_TYPE_TEAP, "TEAP");
1610 	if (!eap)
1611 		return -1;
1612 
1613 	eap->init = eap_teap_init;
1614 	eap->deinit = eap_teap_deinit;
1615 	eap->process = eap_teap_process;
1616 	eap->isKeyAvailable = eap_teap_isKeyAvailable;
1617 	eap->getKey = eap_teap_getKey;
1618 	eap->getSessionId = eap_teap_get_session_id;
1619 	eap->get_status = eap_teap_get_status;
1620 #if 0 /* TODO */
1621 	eap->has_reauth_data = eap_teap_has_reauth_data;
1622 	eap->deinit_for_reauth = eap_teap_deinit_for_reauth;
1623 	eap->init_for_reauth = eap_teap_init_for_reauth;
1624 #endif
1625 	eap->get_emsk = eap_teap_get_emsk;
1626 
1627 	return eap_peer_method_register(eap);
1628 }
1629