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