]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/eap_peer/eap_teap.c
EAP-TEAP peer: Add Intermediate-Result TLV with Crypto-Binding TLV
[thirdparty/hostap.git] / src / eap_peer / eap_teap.c
1 /*
2 * EAP peer method: EAP-TEAP (RFC 7170)
3 * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "crypto/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 #include "eap_teap_pac.h"
18
19 #ifdef EAP_TEAP_DYNAMIC
20 #include "eap_teap_pac.c"
21 #endif /* EAP_TEAP_DYNAMIC */
22
23
24 static void eap_teap_deinit(struct eap_sm *sm, void *priv);
25
26
27 struct eap_teap_data {
28 struct eap_ssl_data ssl;
29
30 u8 teap_version; /* Negotiated version */
31 u8 received_version; /* Version number received during negotiation */
32 u16 tls_cs;
33
34 const struct eap_method *phase2_method;
35 void *phase2_priv;
36 int phase2_success;
37 int inner_method_done;
38 int result_success_done;
39 int on_tx_completion;
40
41 struct eap_method_type phase2_type;
42 struct eap_method_type *phase2_types;
43 size_t num_phase2_types;
44 int resuming; /* starting a resumed session */
45 #define EAP_TEAP_PROV_UNAUTH 1
46 #define EAP_TEAP_PROV_AUTH 2
47 int provisioning_allowed; /* Allowed PAC provisioning modes */
48 int provisioning; /* doing PAC provisioning (not the normal auth) */
49 int anon_provisioning; /* doing anonymous (unauthenticated)
50 * provisioning */
51 int session_ticket_used;
52 int test_outer_tlvs;
53
54 u8 key_data[EAP_TEAP_KEY_LEN];
55 u8 *session_id;
56 size_t id_len;
57 u8 emsk[EAP_EMSK_LEN];
58 int success;
59
60 struct eap_teap_pac *pac;
61 struct eap_teap_pac *current_pac;
62 size_t max_pac_list_len;
63 int use_pac_binary_format;
64
65 u8 simck_msk[EAP_TEAP_SIMCK_LEN];
66 u8 simck_emsk[EAP_TEAP_SIMCK_LEN];
67 int simck_idx;
68 int cmk_emsk_available;
69
70 struct wpabuf *pending_phase2_req;
71 struct wpabuf *pending_resp;
72 struct wpabuf *server_outer_tlvs;
73 struct wpabuf *peer_outer_tlvs;
74 };
75
76
77 static int eap_teap_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
78 const u8 *client_random,
79 const u8 *server_random,
80 u8 *master_secret)
81 {
82 struct eap_teap_data *data = ctx;
83
84 wpa_printf(MSG_DEBUG, "EAP-TEAP: SessionTicket callback");
85
86 if (!master_secret) {
87 wpa_printf(MSG_DEBUG,
88 "EAP-TEAP: SessionTicket failed - fall back to full TLS handshake");
89 data->session_ticket_used = 0;
90 if (data->provisioning_allowed) {
91 wpa_printf(MSG_DEBUG,
92 "EAP-TEAP: Try to provision a new PAC-Key");
93 data->provisioning = 1;
94 data->current_pac = NULL;
95 }
96 return 0;
97 }
98
99 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: SessionTicket", ticket, len);
100
101 if (!data->current_pac) {
102 wpa_printf(MSG_DEBUG,
103 "EAP-TEAP: No PAC-Key available for using SessionTicket");
104 data->session_ticket_used = 0;
105 return 0;
106 }
107
108 /* EAP-TEAP uses PAC-Key as the TLS master_secret */
109 os_memcpy(master_secret, data->current_pac->pac_key,
110 EAP_TEAP_PAC_KEY_LEN);
111
112 data->session_ticket_used = 1;
113
114 return 1;
115 }
116
117
118 static void eap_teap_parse_phase1(struct eap_teap_data *data,
119 const char *phase1)
120 {
121 const char *pos;
122
123 pos = os_strstr(phase1, "teap_provisioning=");
124 if (pos) {
125 data->provisioning_allowed = atoi(pos + 18);
126 wpa_printf(MSG_DEBUG,
127 "EAP-TEAP: Automatic PAC provisioning mode: %d",
128 data->provisioning_allowed);
129 }
130
131 pos = os_strstr(phase1, "teap_max_pac_list_len=");
132 if (pos) {
133 data->max_pac_list_len = atoi(pos + 22);
134 if (data->max_pac_list_len == 0)
135 data->max_pac_list_len = 1;
136 wpa_printf(MSG_DEBUG, "EAP-TEAP: Maximum PAC list length: %lu",
137 (unsigned long) data->max_pac_list_len);
138 }
139
140 if (os_strstr(phase1, "teap_pac_format=binary")) {
141 data->use_pac_binary_format = 1;
142 wpa_printf(MSG_DEBUG,
143 "EAP-TEAP: Using binary format for PAC list");
144 }
145
146 #ifdef CONFIG_TESTING_OPTIONS
147 if (os_strstr(phase1, "teap_test_outer_tlvs=1"))
148 data->test_outer_tlvs = 1;
149 #endif /* CONFIG_TESTING_OPTIONS */
150 }
151
152
153 static void * eap_teap_init(struct eap_sm *sm)
154 {
155 struct eap_teap_data *data;
156 struct eap_peer_config *config = eap_get_config(sm);
157
158 if (!config)
159 return NULL;
160
161 data = os_zalloc(sizeof(*data));
162 if (!data)
163 return NULL;
164 data->teap_version = EAP_TEAP_VERSION;
165 data->max_pac_list_len = 10;
166
167 if (config->phase1)
168 eap_teap_parse_phase1(data, config->phase1);
169
170 if ((data->provisioning_allowed & EAP_TEAP_PROV_AUTH) &&
171 !config->ca_cert && !config->ca_path) {
172 /* Prevent PAC provisioning without mutual authentication
173 * (either by validating server certificate or by suitable
174 * inner EAP method). */
175 wpa_printf(MSG_INFO,
176 "EAP-TEAP: Disable authenticated provisioning due to no ca_cert/ca_path");
177 data->provisioning_allowed &= ~EAP_TEAP_PROV_AUTH;
178 }
179
180 if (eap_peer_select_phase2_methods(config, "auth=",
181 &data->phase2_types,
182 &data->num_phase2_types) < 0) {
183 eap_teap_deinit(sm, data);
184 return NULL;
185 }
186
187 data->phase2_type.vendor = EAP_VENDOR_IETF;
188 data->phase2_type.method = EAP_TYPE_NONE;
189
190 config->teap_anon_dh = !!(data->provisioning_allowed &
191 EAP_TEAP_PROV_UNAUTH);
192 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TEAP)) {
193 wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL");
194 eap_teap_deinit(sm, data);
195 return NULL;
196 }
197
198 if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
199 eap_teap_session_ticket_cb,
200 data) < 0) {
201 wpa_printf(MSG_INFO,
202 "EAP-TEAP: Failed to set SessionTicket callback");
203 eap_teap_deinit(sm, data);
204 return NULL;
205 }
206
207 if (!config->pac_file) {
208 wpa_printf(MSG_INFO, "EAP-TEAP: No PAC file configured");
209 eap_teap_deinit(sm, data);
210 return NULL;
211 }
212
213 if (data->use_pac_binary_format &&
214 eap_teap_load_pac_bin(sm, &data->pac, config->pac_file) < 0) {
215 wpa_printf(MSG_INFO, "EAP-TEAP: Failed to load PAC file");
216 eap_teap_deinit(sm, data);
217 return NULL;
218 }
219
220 if (!data->use_pac_binary_format &&
221 eap_teap_load_pac(sm, &data->pac, config->pac_file) < 0) {
222 wpa_printf(MSG_INFO, "EAP-TEAP: Failed to load PAC file");
223 eap_teap_deinit(sm, data);
224 return NULL;
225 }
226 eap_teap_pac_list_truncate(data->pac, data->max_pac_list_len);
227
228 return data;
229 }
230
231
232 static void eap_teap_clear(struct eap_teap_data *data)
233 {
234 forced_memzero(data->key_data, EAP_TEAP_KEY_LEN);
235 forced_memzero(data->emsk, EAP_EMSK_LEN);
236 os_free(data->session_id);
237 data->session_id = NULL;
238 wpabuf_free(data->pending_phase2_req);
239 data->pending_phase2_req = NULL;
240 wpabuf_free(data->pending_resp);
241 data->pending_resp = NULL;
242 wpabuf_free(data->server_outer_tlvs);
243 data->server_outer_tlvs = NULL;
244 wpabuf_free(data->peer_outer_tlvs);
245 data->peer_outer_tlvs = NULL;
246 forced_memzero(data->simck_msk, EAP_TEAP_SIMCK_LEN);
247 forced_memzero(data->simck_emsk, EAP_TEAP_SIMCK_LEN);
248 }
249
250
251 static void eap_teap_deinit(struct eap_sm *sm, void *priv)
252 {
253 struct eap_teap_data *data = priv;
254 struct eap_teap_pac *pac, *prev;
255
256 if (!data)
257 return;
258 if (data->phase2_priv && data->phase2_method)
259 data->phase2_method->deinit(sm, data->phase2_priv);
260 eap_teap_clear(data);
261 os_free(data->phase2_types);
262 eap_peer_tls_ssl_deinit(sm, &data->ssl);
263
264 pac = data->pac;
265 prev = NULL;
266 while (pac) {
267 prev = pac;
268 pac = pac->next;
269 eap_teap_free_pac(prev);
270 }
271
272 os_free(data);
273 }
274
275
276 static int eap_teap_derive_msk(struct eap_teap_data *data)
277 {
278 /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
279 * is used in this derivation */
280 if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
281 data->key_data) < 0 ||
282 eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
283 data->emsk) < 0)
284 return -1;
285 data->success = 1;
286 return 0;
287 }
288
289
290 static int eap_teap_derive_key_auth(struct eap_sm *sm,
291 struct eap_teap_data *data)
292 {
293 int res;
294
295 /* RFC 7170, Section 5.1 */
296 res = tls_connection_export_key(sm->ssl_ctx, data->ssl.conn,
297 TEAP_TLS_EXPORTER_LABEL_SKS, NULL, 0,
298 data->simck_msk, EAP_TEAP_SIMCK_LEN);
299 if (res)
300 return res;
301 wpa_hexdump_key(MSG_DEBUG,
302 "EAP-TEAP: session_key_seed (S-IMCK[0])",
303 data->simck_msk, EAP_TEAP_SIMCK_LEN);
304 os_memcpy(data->simck_emsk, data->simck_msk, EAP_TEAP_SIMCK_LEN);
305 data->simck_idx = 0;
306 return 0;
307 }
308
309
310 static int eap_teap_init_phase2_method(struct eap_sm *sm,
311 struct eap_teap_data *data)
312 {
313 data->inner_method_done = 0;
314 data->phase2_method =
315 eap_peer_get_eap_method(data->phase2_type.vendor,
316 data->phase2_type.method);
317 if (!data->phase2_method)
318 return -1;
319
320 sm->init_phase2 = 1;
321 data->phase2_priv = data->phase2_method->init(sm);
322 sm->init_phase2 = 0;
323
324 return data->phase2_priv == NULL ? -1 : 0;
325 }
326
327
328 static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
329 {
330 size_t i;
331
332 /* TODO: TNC with anonymous provisioning; need to require both
333 * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
334
335 if (data->anon_provisioning &&
336 !eap_teap_allowed_anon_prov_phase2_method(type)) {
337 wpa_printf(MSG_INFO,
338 "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
339 type);
340 return -1;
341 }
342
343 #ifdef EAP_TNC
344 if (type == EAP_TYPE_TNC) {
345 data->phase2_type.vendor = EAP_VENDOR_IETF;
346 data->phase2_type.method = EAP_TYPE_TNC;
347 wpa_printf(MSG_DEBUG,
348 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
349 data->phase2_type.vendor,
350 data->phase2_type.method);
351 return 0;
352 }
353 #endif /* EAP_TNC */
354
355 for (i = 0; i < data->num_phase2_types; i++) {
356 if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
357 data->phase2_types[i].method != type)
358 continue;
359
360 data->phase2_type.vendor = data->phase2_types[i].vendor;
361 data->phase2_type.method = data->phase2_types[i].method;
362 wpa_printf(MSG_DEBUG,
363 "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
364 data->phase2_type.vendor,
365 data->phase2_type.method);
366 break;
367 }
368
369 if (type != data->phase2_type.method || type == EAP_TYPE_NONE)
370 return -1;
371
372 return 0;
373 }
374
375
376 static int eap_teap_phase2_request(struct eap_sm *sm,
377 struct eap_teap_data *data,
378 struct eap_method_ret *ret,
379 struct eap_hdr *hdr,
380 struct wpabuf **resp)
381 {
382 size_t len = be_to_host16(hdr->length);
383 u8 *pos;
384 struct eap_method_ret iret;
385 struct eap_peer_config *config = eap_get_config(sm);
386 struct wpabuf msg;
387
388 if (len <= sizeof(struct eap_hdr)) {
389 wpa_printf(MSG_INFO,
390 "EAP-TEAP: too short Phase 2 request (len=%lu)",
391 (unsigned long) len);
392 return -1;
393 }
394 pos = (u8 *) (hdr + 1);
395 wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%d", *pos);
396 if (*pos == EAP_TYPE_IDENTITY) {
397 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
398 return 0;
399 }
400
401 if (data->phase2_priv && data->phase2_method &&
402 *pos != data->phase2_type.method) {
403 wpa_printf(MSG_DEBUG,
404 "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
405 data->phase2_method->deinit(sm, data->phase2_priv);
406 data->phase2_method = NULL;
407 data->phase2_priv = NULL;
408 data->phase2_type.vendor = EAP_VENDOR_IETF;
409 data->phase2_type.method = EAP_TYPE_NONE;
410 }
411
412 if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
413 data->phase2_type.method == EAP_TYPE_NONE &&
414 eap_teap_select_phase2_method(data, *pos) < 0) {
415 if (eap_peer_tls_phase2_nak(data->phase2_types,
416 data->num_phase2_types,
417 hdr, resp))
418 return -1;
419 return 0;
420 }
421
422 if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
423 !data->phase2_method) {
424 wpa_printf(MSG_INFO,
425 "EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
426 *pos);
427 ret->methodState = METHOD_DONE;
428 ret->decision = DECISION_FAIL;
429 return -1;
430 }
431
432 os_memset(&iret, 0, sizeof(iret));
433 wpabuf_set(&msg, hdr, len);
434 *resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
435 &msg);
436 if (iret.methodState == METHOD_DONE)
437 data->inner_method_done = 1;
438 if (!(*resp) ||
439 (iret.methodState == METHOD_DONE &&
440 iret.decision == DECISION_FAIL)) {
441 ret->methodState = METHOD_DONE;
442 ret->decision = DECISION_FAIL;
443 } else if ((iret.methodState == METHOD_DONE ||
444 iret.methodState == METHOD_MAY_CONT) &&
445 (iret.decision == DECISION_UNCOND_SUCC ||
446 iret.decision == DECISION_COND_SUCC)) {
447 data->phase2_success = 1;
448 }
449
450 if (!(*resp) && config &&
451 (config->pending_req_identity || config->pending_req_password ||
452 config->pending_req_otp || config->pending_req_new_password ||
453 config->pending_req_sim)) {
454 wpabuf_free(data->pending_phase2_req);
455 data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
456 } else if (!(*resp))
457 return -1;
458
459 return 0;
460 }
461
462
463 static struct wpabuf * eap_teap_tlv_nak(int vendor_id, int tlv_type)
464 {
465 struct wpabuf *buf;
466 struct teap_tlv_nak *nak;
467
468 wpa_printf(MSG_DEBUG,
469 "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
470 vendor_id, tlv_type);
471 buf = wpabuf_alloc(sizeof(*nak));
472 if (!buf)
473 return NULL;
474 nak = wpabuf_put(buf, sizeof(*nak));
475 nak->tlv_type = host_to_be16(TEAP_TLV_MANDATORY | TEAP_TLV_NAK);
476 nak->length = host_to_be16(6);
477 nak->vendor_id = host_to_be32(vendor_id);
478 nak->nak_type = host_to_be16(tlv_type);
479 return buf;
480 }
481
482
483 static struct wpabuf * eap_teap_tlv_pac_ack(void)
484 {
485 struct wpabuf *buf;
486 struct teap_tlv_result *res;
487 struct teap_tlv_pac_ack *ack;
488
489 buf = wpabuf_alloc(sizeof(*res) + sizeof(*ack));
490 if (!buf)
491 return NULL;
492
493 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC TLV (ack)");
494 ack = wpabuf_put(buf, sizeof(*ack));
495 ack->tlv_type = host_to_be16(TEAP_TLV_PAC | TEAP_TLV_MANDATORY);
496 ack->length = host_to_be16(sizeof(*ack) - sizeof(struct teap_tlv_hdr));
497 ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT);
498 ack->pac_len = host_to_be16(2);
499 ack->result = host_to_be16(TEAP_STATUS_SUCCESS);
500
501 return buf;
502 }
503
504
505 static struct wpabuf * eap_teap_process_eap_payload_tlv(
506 struct eap_sm *sm, struct eap_teap_data *data,
507 struct eap_method_ret *ret,
508 u8 *eap_payload_tlv, size_t eap_payload_tlv_len)
509 {
510 struct eap_hdr *hdr;
511 struct wpabuf *resp = NULL;
512
513 if (eap_payload_tlv_len < sizeof(*hdr)) {
514 wpa_printf(MSG_DEBUG,
515 "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
516 (unsigned long) eap_payload_tlv_len);
517 return NULL;
518 }
519
520 hdr = (struct eap_hdr *) eap_payload_tlv;
521 if (be_to_host16(hdr->length) > eap_payload_tlv_len) {
522 wpa_printf(MSG_DEBUG,
523 "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
524 return NULL;
525 }
526
527 if (hdr->code != EAP_CODE_REQUEST) {
528 wpa_printf(MSG_INFO,
529 "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
530 hdr->code);
531 return NULL;
532 }
533
534 if (eap_teap_phase2_request(sm, data, ret, hdr, &resp)) {
535 wpa_printf(MSG_INFO,
536 "EAP-TEAP: Phase 2 Request processing failed");
537 return NULL;
538 }
539
540 return eap_teap_tlv_eap_payload(resp);
541 }
542
543
544 static struct wpabuf * eap_teap_process_basic_auth_req(
545 struct eap_sm *sm, struct eap_teap_data *data,
546 u8 *basic_auth_req, size_t basic_auth_req_len)
547 {
548 const u8 *identity, *password;
549 size_t identity_len, password_len, plen;
550 struct wpabuf *resp;
551
552 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Req prompt",
553 basic_auth_req, basic_auth_req_len);
554 /* TODO: send over control interface */
555
556 identity = eap_get_config_identity(sm, &identity_len);
557 password = eap_get_config_password(sm, &password_len);
558 if (!identity || !password ||
559 identity_len > 255 || password_len > 255) {
560 wpa_printf(MSG_DEBUG,
561 "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
562 return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ);
563 }
564
565 plen = 1 + identity_len + 1 + password_len;
566 resp = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + plen);
567 if (!resp)
568 return NULL;
569 eap_teap_put_tlv_hdr(resp, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP, plen);
570 wpabuf_put_u8(resp, identity_len);
571 wpabuf_put_data(resp, identity, identity_len);
572 wpabuf_put_u8(resp, password_len);
573 wpabuf_put_data(resp, password, password_len);
574 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Resp",
575 resp);
576
577 /* Assume this succeeds so that Result TLV(Success) from the server can
578 * be used to terminate TEAP. */
579 data->phase2_success = 1;
580
581 return resp;
582 }
583
584
585 static int
586 eap_teap_validate_crypto_binding(struct eap_teap_data *data,
587 const struct teap_tlv_crypto_binding *cb)
588 {
589 u8 flags, subtype;
590
591 subtype = cb->subtype & 0x0f;
592 flags = cb->subtype >> 4;
593
594 wpa_printf(MSG_DEBUG,
595 "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
596 cb->version, cb->received_version, flags, subtype);
597 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
598 cb->nonce, sizeof(cb->nonce));
599 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
600 cb->emsk_compound_mac, sizeof(cb->emsk_compound_mac));
601 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
602 cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
603
604 if (cb->version != EAP_TEAP_VERSION ||
605 cb->received_version != data->received_version ||
606 subtype != TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST ||
607 flags < 1 || flags > 3) {
608 wpa_printf(MSG_INFO,
609 "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
610 cb->version, cb->received_version, flags, subtype);
611 return -1;
612 }
613
614 if (cb->nonce[EAP_TEAP_NONCE_LEN - 1] & 0x01) {
615 wpa_printf(MSG_INFO,
616 "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
617 return -1;
618 }
619
620 return 0;
621 }
622
623
624 static int eap_teap_write_crypto_binding(
625 struct eap_teap_data *data,
626 struct teap_tlv_crypto_binding *rbind,
627 const struct teap_tlv_crypto_binding *cb,
628 const u8 *cmk_msk, const u8 *cmk_emsk)
629 {
630 u8 subtype, flags;
631
632 rbind->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
633 TEAP_TLV_CRYPTO_BINDING);
634 rbind->length = host_to_be16(sizeof(*rbind) -
635 sizeof(struct teap_tlv_hdr));
636 rbind->version = EAP_TEAP_VERSION;
637 rbind->received_version = data->received_version;
638 /* FIX: RFC 7170 is not clear on which Flags value to use when
639 * Crypto-Binding TLV is used with Basic-Password-Auth */
640 flags = cmk_emsk ? TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC :
641 TEAP_CRYPTO_BINDING_MSK_CMAC;
642 subtype = TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE;
643 rbind->subtype = (flags << 4) | subtype;
644 os_memcpy(rbind->nonce, cb->nonce, sizeof(cb->nonce));
645 inc_byte_array(rbind->nonce, sizeof(rbind->nonce));
646 os_memset(rbind->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
647 os_memset(rbind->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
648
649 if (eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
650 data->peer_outer_tlvs, cmk_msk,
651 rbind->msk_compound_mac) < 0)
652 return -1;
653 if (cmk_emsk &&
654 eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
655 data->peer_outer_tlvs, cmk_emsk,
656 rbind->emsk_compound_mac) < 0)
657 return -1;
658
659 wpa_printf(MSG_DEBUG,
660 "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
661 rbind->version, rbind->received_version, flags, subtype);
662 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
663 rbind->nonce, sizeof(rbind->nonce));
664 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
665 rbind->emsk_compound_mac, sizeof(rbind->emsk_compound_mac));
666 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
667 rbind->msk_compound_mac, sizeof(rbind->msk_compound_mac));
668
669 return 0;
670 }
671
672
673 static int eap_teap_get_cmk(struct eap_sm *sm, struct eap_teap_data *data,
674 u8 *cmk_msk, u8 *cmk_emsk)
675 {
676 u8 *msk = NULL, *emsk = NULL;
677 size_t msk_len = 0, emsk_len = 0;
678 int res;
679
680 wpa_printf(MSG_DEBUG,
681 "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
682 data->simck_idx + 1);
683
684 if (!data->phase2_method)
685 return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
686 data->simck_msk,
687 cmk_msk);
688
689 if (!data->phase2_method || !data->phase2_priv) {
690 wpa_printf(MSG_INFO, "EAP-TEAP: Phase 2 method not available");
691 return -1;
692 }
693
694 if (data->phase2_method->isKeyAvailable &&
695 !data->phase2_method->isKeyAvailable(sm, data->phase2_priv)) {
696 wpa_printf(MSG_INFO,
697 "EAP-TEAP: Phase 2 key material not available");
698 return -1;
699 }
700
701 if (data->phase2_method->isKeyAvailable &&
702 data->phase2_method->getKey) {
703 msk = data->phase2_method->getKey(sm, data->phase2_priv,
704 &msk_len);
705 if (!msk) {
706 wpa_printf(MSG_INFO,
707 "EAP-TEAP: Could not fetch Phase 2 MSK");
708 return -1;
709 }
710 }
711
712 if (data->phase2_method->isKeyAvailable &&
713 data->phase2_method->get_emsk) {
714 emsk = data->phase2_method->get_emsk(sm, data->phase2_priv,
715 &emsk_len);
716 }
717
718 res = eap_teap_derive_imck(data->tls_cs,
719 data->simck_msk, data->simck_emsk,
720 msk, msk_len, emsk, emsk_len,
721 data->simck_msk, cmk_msk,
722 data->simck_emsk, cmk_emsk);
723 bin_clear_free(msk, msk_len);
724 bin_clear_free(emsk, emsk_len);
725 if (res == 0) {
726 data->simck_idx++;
727 if (emsk)
728 data->cmk_emsk_available = 1;
729 }
730 return res;
731 }
732
733
734 static int eap_teap_session_id(struct eap_teap_data *data)
735 {
736 const size_t max_id_len = 100;
737 int res;
738
739 os_free(data->session_id);
740 data->session_id = os_malloc(max_id_len);
741 if (!data->session_id)
742 return -1;
743
744 data->session_id[0] = EAP_TYPE_TEAP;
745 res = tls_get_tls_unique(data->ssl.conn, data->session_id + 1,
746 max_id_len - 1);
747 if (res < 0) {
748 os_free(data->session_id);
749 data->session_id = NULL;
750 wpa_printf(MSG_ERROR, "EAP-TEAP: Failed to derive Session-Id");
751 return -1;
752 }
753
754 data->id_len = 1 + res;
755 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Derived Session-Id",
756 data->session_id, data->id_len);
757 return 0;
758 }
759
760
761 static struct wpabuf * eap_teap_process_crypto_binding(
762 struct eap_sm *sm, struct eap_teap_data *data,
763 struct eap_method_ret *ret,
764 const struct teap_tlv_crypto_binding *cb, size_t bind_len)
765 {
766 struct wpabuf *resp;
767 u8 *pos;
768 u8 cmk_msk[EAP_TEAP_CMK_LEN];
769 u8 cmk_emsk[EAP_TEAP_CMK_LEN];
770 const u8 *cmk_emsk_ptr = NULL;
771 int res;
772 size_t len;
773 u8 flags;
774
775 if (eap_teap_validate_crypto_binding(data, cb) < 0 ||
776 eap_teap_get_cmk(sm, data, cmk_msk, cmk_emsk) < 0)
777 return NULL;
778
779 /* Validate received MSK/EMSK Compound MAC */
780 flags = cb->subtype >> 4;
781
782 if (flags == TEAP_CRYPTO_BINDING_MSK_CMAC ||
783 flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) {
784 u8 msk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
785
786 if (eap_teap_compound_mac(data->tls_cs, cb,
787 data->server_outer_tlvs,
788 data->peer_outer_tlvs, cmk_msk,
789 msk_compound_mac) < 0)
790 return NULL;
791 res = os_memcmp_const(msk_compound_mac, cb->msk_compound_mac,
792 EAP_TEAP_COMPOUND_MAC_LEN);
793 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received MSK Compound MAC",
794 cb->msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
795 wpa_hexdump(MSG_MSGDUMP,
796 "EAP-TEAP: Calculated MSK Compound MAC",
797 msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
798 if (res != 0) {
799 wpa_printf(MSG_INFO,
800 "EAP-TEAP: MSK Compound MAC did not match");
801 return NULL;
802 }
803 }
804
805 if ((flags == TEAP_CRYPTO_BINDING_EMSK_CMAC ||
806 flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) &&
807 data->cmk_emsk_available) {
808 u8 emsk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
809
810 if (eap_teap_compound_mac(data->tls_cs, cb,
811 data->server_outer_tlvs,
812 data->peer_outer_tlvs, cmk_emsk,
813 emsk_compound_mac) < 0)
814 return NULL;
815 res = os_memcmp_const(emsk_compound_mac, cb->emsk_compound_mac,
816 EAP_TEAP_COMPOUND_MAC_LEN);
817 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received EMSK Compound MAC",
818 cb->emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
819 wpa_hexdump(MSG_MSGDUMP,
820 "EAP-TEAP: Calculated EMSK Compound MAC",
821 emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
822 if (res != 0) {
823 wpa_printf(MSG_INFO,
824 "EAP-TEAP: EMSK Compound MAC did not match");
825 return NULL;
826 }
827
828 cmk_emsk_ptr = cmk_emsk;
829 }
830
831 if (flags == TEAP_CRYPTO_BINDING_EMSK_CMAC &&
832 !data->cmk_emsk_available) {
833 wpa_printf(MSG_INFO,
834 "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
835 return NULL;
836 }
837
838 /*
839 * Compound MAC was valid, so authentication succeeded. Reply with
840 * crypto binding to allow server to complete authentication.
841 */
842
843 len = sizeof(struct teap_tlv_crypto_binding);
844 resp = wpabuf_alloc(len);
845 if (!resp)
846 return NULL;
847
848 if (data->phase2_success && eap_teap_derive_msk(data) < 0) {
849 wpa_printf(MSG_INFO, "EAP-TEAP: Failed to generate MSK");
850 ret->methodState = METHOD_DONE;
851 ret->decision = DECISION_FAIL;
852 data->phase2_success = 0;
853 wpabuf_free(resp);
854 return NULL;
855 }
856
857 if (data->phase2_success && eap_teap_session_id(data) < 0) {
858 wpabuf_free(resp);
859 return NULL;
860 }
861
862 pos = wpabuf_put(resp, sizeof(struct teap_tlv_crypto_binding));
863 if (eap_teap_write_crypto_binding(
864 data, (struct teap_tlv_crypto_binding *) pos,
865 cb, cmk_msk, cmk_emsk_ptr) < 0) {
866 wpabuf_free(resp);
867 return NULL;
868 }
869
870 return resp;
871 }
872
873
874 static void eap_teap_parse_pac_tlv(struct eap_teap_pac *entry, int type,
875 u8 *pos, size_t len, int *pac_key_found)
876 {
877 switch (type & 0x7fff) {
878 case PAC_TYPE_PAC_KEY:
879 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: PAC-Key", pos, len);
880 if (len != EAP_TEAP_PAC_KEY_LEN) {
881 wpa_printf(MSG_DEBUG,
882 "EAP-TEAP: Invalid PAC-Key length %lu",
883 (unsigned long) len);
884 break;
885 }
886 *pac_key_found = 1;
887 os_memcpy(entry->pac_key, pos, len);
888 break;
889 case PAC_TYPE_PAC_OPAQUE:
890 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: PAC-Opaque", pos, len);
891 entry->pac_opaque = pos;
892 entry->pac_opaque_len = len;
893 break;
894 case PAC_TYPE_PAC_INFO:
895 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: PAC-Info", pos, len);
896 entry->pac_info = pos;
897 entry->pac_info_len = len;
898 break;
899 default:
900 wpa_printf(MSG_DEBUG, "EAP-TEAP: Ignored unknown PAC type %d",
901 type);
902 break;
903 }
904 }
905
906
907 static int eap_teap_process_pac_tlv(struct eap_teap_pac *entry,
908 u8 *pac, size_t pac_len)
909 {
910 struct pac_attr_hdr *hdr;
911 u8 *pos;
912 size_t left, len;
913 int type, pac_key_found = 0;
914
915 pos = pac;
916 left = pac_len;
917
918 while (left > sizeof(*hdr)) {
919 hdr = (struct pac_attr_hdr *) pos;
920 type = be_to_host16(hdr->type);
921 len = be_to_host16(hdr->len);
922 pos += sizeof(*hdr);
923 left -= sizeof(*hdr);
924 if (len > left) {
925 wpa_printf(MSG_DEBUG,
926 "EAP-TEAP: PAC TLV overrun (type=%d len=%lu left=%lu)",
927 type, (unsigned long) len,
928 (unsigned long) left);
929 return -1;
930 }
931
932 eap_teap_parse_pac_tlv(entry, type, pos, len, &pac_key_found);
933
934 pos += len;
935 left -= len;
936 }
937
938 if (!pac_key_found || !entry->pac_opaque || !entry->pac_info) {
939 wpa_printf(MSG_DEBUG,
940 "EAP-TEAP: PAC TLV does not include all the required fields");
941 return -1;
942 }
943
944 return 0;
945 }
946
947
948 static int eap_teap_parse_pac_info(struct eap_teap_pac *entry, int type,
949 u8 *pos, size_t len)
950 {
951 u16 pac_type;
952 u32 lifetime;
953 struct os_time now;
954
955 switch (type & 0x7fff) {
956 case PAC_TYPE_CRED_LIFETIME:
957 if (len != 4) {
958 wpa_hexdump(MSG_DEBUG,
959 "EAP-TEAP: PAC-Info - Invalid CRED_LIFETIME length - ignored",
960 pos, len);
961 return 0;
962 }
963
964 /*
965 * This is not currently saved separately in PAC files since
966 * the server can automatically initiate PAC update when
967 * needed. Anyway, the information is available from PAC-Info
968 * dump if it is needed for something in the future.
969 */
970 lifetime = WPA_GET_BE32(pos);
971 os_get_time(&now);
972 wpa_printf(MSG_DEBUG,
973 "EAP-TEAP: PAC-Info - CRED_LIFETIME %d (%d days)",
974 lifetime, (lifetime - (u32) now.sec) / 86400);
975 break;
976 case PAC_TYPE_A_ID:
977 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - A-ID",
978 pos, len);
979 entry->a_id = pos;
980 entry->a_id_len = len;
981 break;
982 case PAC_TYPE_I_ID:
983 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - I-ID",
984 pos, len);
985 entry->i_id = pos;
986 entry->i_id_len = len;
987 break;
988 case PAC_TYPE_A_ID_INFO:
989 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - A-ID-Info",
990 pos, len);
991 entry->a_id_info = pos;
992 entry->a_id_info_len = len;
993 break;
994 case PAC_TYPE_PAC_TYPE:
995 /* RFC 7170, Section 4.2.12.6 - PAC-Type TLV */
996 if (len != 2) {
997 wpa_printf(MSG_INFO,
998 "EAP-TEAP: Invalid PAC-Type length %lu (expected 2)",
999 (unsigned long) len);
1000 wpa_hexdump_ascii(MSG_DEBUG,
1001 "EAP-TEAP: PAC-Info - PAC-Type",
1002 pos, len);
1003 return -1;
1004 }
1005 pac_type = WPA_GET_BE16(pos);
1006 if (pac_type != PAC_TYPE_TUNNEL_PAC) {
1007 wpa_printf(MSG_INFO,
1008 "EAP-TEAP: Unsupported PAC Type %d",
1009 pac_type);
1010 return -1;
1011 }
1012
1013 wpa_printf(MSG_DEBUG, "EAP-TEAP: PAC-Info - PAC-Type %d",
1014 pac_type);
1015 entry->pac_type = pac_type;
1016 break;
1017 default:
1018 wpa_printf(MSG_DEBUG,
1019 "EAP-TEAP: Ignored unknown PAC-Info type %d", type);
1020 break;
1021 }
1022
1023 return 0;
1024 }
1025
1026
1027 static int eap_teap_process_pac_info(struct eap_teap_pac *entry)
1028 {
1029 struct pac_attr_hdr *hdr;
1030 u8 *pos;
1031 size_t left, len;
1032 int type;
1033
1034 /* RFC 7170, Section 4.2.12.4 */
1035
1036 /* PAC-Type defaults to Tunnel PAC (Type 1) */
1037 entry->pac_type = PAC_TYPE_TUNNEL_PAC;
1038
1039 pos = entry->pac_info;
1040 left = entry->pac_info_len;
1041 while (left > sizeof(*hdr)) {
1042 hdr = (struct pac_attr_hdr *) pos;
1043 type = be_to_host16(hdr->type);
1044 len = be_to_host16(hdr->len);
1045 pos += sizeof(*hdr);
1046 left -= sizeof(*hdr);
1047 if (len > left) {
1048 wpa_printf(MSG_DEBUG,
1049 "EAP-TEAP: PAC-Info overrun (type=%d len=%lu left=%lu)",
1050 type, (unsigned long) len,
1051 (unsigned long) left);
1052 return -1;
1053 }
1054
1055 if (eap_teap_parse_pac_info(entry, type, pos, len) < 0)
1056 return -1;
1057
1058 pos += len;
1059 left -= len;
1060 }
1061
1062 if (!entry->a_id || !entry->a_id_info) {
1063 wpa_printf(MSG_DEBUG,
1064 "EAP-TEAP: PAC-Info does not include all the required fields");
1065 return -1;
1066 }
1067
1068 return 0;
1069 }
1070
1071
1072 static struct wpabuf * eap_teap_process_pac(struct eap_sm *sm,
1073 struct eap_teap_data *data,
1074 struct eap_method_ret *ret,
1075 u8 *pac, size_t pac_len)
1076 {
1077 struct eap_peer_config *config = eap_get_config(sm);
1078 struct eap_teap_pac entry;
1079
1080 os_memset(&entry, 0, sizeof(entry));
1081 if (eap_teap_process_pac_tlv(&entry, pac, pac_len) ||
1082 eap_teap_process_pac_info(&entry))
1083 return NULL;
1084
1085 eap_teap_add_pac(&data->pac, &data->current_pac, &entry);
1086 eap_teap_pac_list_truncate(data->pac, data->max_pac_list_len);
1087 if (data->use_pac_binary_format)
1088 eap_teap_save_pac_bin(sm, data->pac, config->pac_file);
1089 else
1090 eap_teap_save_pac(sm, data->pac, config->pac_file);
1091
1092 wpa_printf(MSG_DEBUG,
1093 "EAP-TEAP: Send PAC-Acknowledgement - %s initiated provisioning completed successfully",
1094 data->provisioning ? "peer" : "server");
1095 return eap_teap_tlv_pac_ack();
1096 }
1097
1098
1099 static int eap_teap_parse_decrypted(struct wpabuf *decrypted,
1100 struct eap_teap_tlv_parse *tlv,
1101 struct wpabuf **resp)
1102 {
1103 u16 tlv_type;
1104 int mandatory, res;
1105 size_t len;
1106 u8 *pos, *end;
1107
1108 os_memset(tlv, 0, sizeof(*tlv));
1109
1110 /* Parse TLVs from the decrypted Phase 2 data */
1111 pos = wpabuf_mhead(decrypted);
1112 end = pos + wpabuf_len(decrypted);
1113 while (end - pos >= 4) {
1114 mandatory = pos[0] & 0x80;
1115 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
1116 pos += 2;
1117 len = WPA_GET_BE16(pos);
1118 pos += 2;
1119 if (len > (size_t) (end - pos)) {
1120 wpa_printf(MSG_INFO, "EAP-TEAP: TLV overflow");
1121 return -1;
1122 }
1123 wpa_printf(MSG_DEBUG,
1124 "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
1125 tlv_type, eap_teap_tlv_type_str(tlv_type),
1126 (unsigned int) len,
1127 mandatory ? " (mandatory)" : "");
1128
1129 res = eap_teap_parse_tlv(tlv, tlv_type, pos, len);
1130 if (res == -2)
1131 break;
1132 if (res < 0) {
1133 if (mandatory) {
1134 wpa_printf(MSG_DEBUG,
1135 "EAP-TEAP: NAK unknown mandatory TLV type %u",
1136 tlv_type);
1137 *resp = eap_teap_tlv_nak(0, tlv_type);
1138 break;
1139 }
1140
1141 wpa_printf(MSG_DEBUG,
1142 "EAP-TEAP: Ignore unknown optional TLV type %u",
1143 tlv_type);
1144 }
1145
1146 pos += len;
1147 }
1148
1149 return 0;
1150 }
1151
1152
1153 static struct wpabuf * eap_teap_pac_request(void)
1154 {
1155 struct wpabuf *req;
1156 struct teap_tlv_request_action *act;
1157 struct teap_tlv_hdr *pac;
1158 struct teap_attr_pac_type *type;
1159
1160 req = wpabuf_alloc(sizeof(*act) + sizeof(*pac) + sizeof(*type));
1161 if (!req)
1162 return NULL;
1163
1164 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Request Action TLV (Process TLV)");
1165 act = wpabuf_put(req, sizeof(*act));
1166 act->tlv_type = host_to_be16(TEAP_TLV_REQUEST_ACTION);
1167 act->length = host_to_be16(2);
1168 act->status = TEAP_STATUS_SUCCESS;
1169 act->action = TEAP_REQUEST_ACTION_PROCESS_TLV;
1170
1171 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC TLV (PAC-Type = Tunnel)");
1172 pac = wpabuf_put(req, sizeof(*pac));
1173 pac->tlv_type = host_to_be16(TEAP_TLV_PAC);
1174 pac->length = host_to_be16(sizeof(*type));
1175
1176 type = wpabuf_put(req, sizeof(*type));
1177 type->type = host_to_be16(PAC_TYPE_PAC_TYPE);
1178 type->length = host_to_be16(2);
1179 type->pac_type = host_to_be16(PAC_TYPE_TUNNEL_PAC);
1180
1181 return req;
1182 }
1183
1184
1185 static int eap_teap_process_decrypted(struct eap_sm *sm,
1186 struct eap_teap_data *data,
1187 struct eap_method_ret *ret,
1188 u8 identifier,
1189 struct wpabuf *decrypted,
1190 struct wpabuf **out_data)
1191 {
1192 struct wpabuf *resp = NULL, *tmp;
1193 struct eap_teap_tlv_parse tlv;
1194 int failed = 0;
1195 enum teap_error_codes error = 0;
1196 int iresult_added = 0;
1197
1198 if (eap_teap_parse_decrypted(decrypted, &tlv, &resp) < 0) {
1199 /* Parsing failed - no response available */
1200 return 0;
1201 }
1202
1203 if (resp) {
1204 /* Parsing rejected the message - send out an error response */
1205 goto send_resp;
1206 }
1207
1208 if (tlv.result == TEAP_STATUS_FAILURE) {
1209 /* Server indicated failure - respond similarly per
1210 * RFC 7170, 3.6.3. This authentication exchange cannot succeed
1211 * and will be terminated with a cleartext EAP Failure. */
1212 wpa_printf(MSG_DEBUG,
1213 "EAP-TEAP: Server rejected authentication");
1214 resp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
1215 ret->methodState = METHOD_DONE;
1216 ret->decision = DECISION_FAIL;
1217 goto send_resp;
1218 }
1219
1220 if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
1221 (!data->result_success_done &&
1222 tlv.result == TEAP_STATUS_SUCCESS)) &&
1223 !tlv.crypto_binding) {
1224 /* Result TLV or Intermediate-Result TLV indicating success,
1225 * but no Crypto-Binding TLV */
1226 wpa_printf(MSG_DEBUG,
1227 "EAP-TEAP: Result TLV or Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
1228 failed = 1;
1229 error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
1230 goto done;
1231 }
1232
1233 if (tlv.iresult != TEAP_STATUS_SUCCESS &&
1234 tlv.iresult != TEAP_STATUS_FAILURE &&
1235 data->inner_method_done) {
1236 wpa_printf(MSG_DEBUG,
1237 "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
1238 failed = 1;
1239 error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
1240 goto done;
1241 }
1242
1243 if (tlv.basic_auth_req) {
1244 tmp = eap_teap_process_basic_auth_req(sm, data,
1245 tlv.basic_auth_req,
1246 tlv.basic_auth_req_len);
1247 if (!tmp)
1248 failed = 1;
1249 resp = wpabuf_concat(resp, tmp);
1250 } else if (tlv.eap_payload_tlv) {
1251 tmp = eap_teap_process_eap_payload_tlv(sm, data, ret,
1252 tlv.eap_payload_tlv,
1253 tlv.eap_payload_tlv_len);
1254 if (!tmp)
1255 failed = 1;
1256 resp = wpabuf_concat(resp, tmp);
1257
1258 if (tlv.iresult == TEAP_STATUS_SUCCESS ||
1259 tlv.iresult == TEAP_STATUS_FAILURE) {
1260 tmp = eap_teap_tlv_result(failed ?
1261 TEAP_STATUS_FAILURE :
1262 TEAP_STATUS_SUCCESS, 1);
1263 resp = wpabuf_concat(resp, tmp);
1264 if (tlv.iresult == TEAP_STATUS_FAILURE)
1265 failed = 1;
1266 iresult_added = 1;
1267 }
1268 }
1269
1270 if (tlv.crypto_binding) {
1271 if (tlv.iresult != TEAP_STATUS_SUCCESS &&
1272 tlv.result != TEAP_STATUS_SUCCESS) {
1273 wpa_printf(MSG_DEBUG,
1274 "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
1275 failed = 1;
1276 error = TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED;
1277 goto done;
1278 }
1279
1280 tmp = eap_teap_process_crypto_binding(sm, data, ret,
1281 tlv.crypto_binding,
1282 tlv.crypto_binding_len);
1283 if (!tmp) {
1284 failed = 1;
1285 error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
1286 } else {
1287 resp = wpabuf_concat(resp, tmp);
1288 if (tlv.result == TEAP_STATUS_SUCCESS && !failed)
1289 data->result_success_done = 1;
1290 if (tlv.iresult == TEAP_STATUS_SUCCESS && !failed)
1291 data->inner_method_done = 0;
1292 }
1293 }
1294
1295 if (data->result_success_done && data->session_ticket_used &&
1296 eap_teap_derive_msk(data) == 0) {
1297 /* Assume the server might accept authentication without going
1298 * through inner authentication. */
1299 wpa_printf(MSG_DEBUG,
1300 "EAP-TEAP: PAC used - server may decide to skip inner authentication");
1301 ret->methodState = METHOD_MAY_CONT;
1302 ret->decision = DECISION_COND_SUCC;
1303 }
1304
1305 if (tlv.pac) {
1306 if (tlv.result == TEAP_STATUS_SUCCESS) {
1307 tmp = eap_teap_process_pac(sm, data, ret,
1308 tlv.pac, tlv.pac_len);
1309 resp = wpabuf_concat(resp, tmp);
1310 } else {
1311 wpa_printf(MSG_DEBUG,
1312 "EAP-TEAP: PAC TLV without Result TLV acknowledging success");
1313 failed = 1;
1314 error = TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED;
1315 }
1316 }
1317
1318 if (!data->current_pac && data->provisioning && !failed && !tlv.pac &&
1319 tlv.crypto_binding &&
1320 (!data->anon_provisioning ||
1321 (data->phase2_success && data->phase2_method &&
1322 data->phase2_method->vendor == 0 &&
1323 eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) &&
1324 eap_teap_allowed_anon_prov_phase2_method(
1325 data->phase2_method->method))) &&
1326 (tlv.iresult == TEAP_STATUS_SUCCESS ||
1327 tlv.result == TEAP_STATUS_SUCCESS)) {
1328 /*
1329 * Need to request Tunnel PAC when using authenticated
1330 * provisioning.
1331 */
1332 wpa_printf(MSG_DEBUG, "EAP-TEAP: Request Tunnel PAC");
1333 tmp = eap_teap_pac_request();
1334 resp = wpabuf_concat(resp, tmp);
1335 }
1336
1337 done:
1338 if (failed) {
1339 tmp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
1340 resp = wpabuf_concat(tmp, resp);
1341
1342 if (error != 0) {
1343 tmp = eap_teap_tlv_error(error);
1344 resp = wpabuf_concat(tmp, resp);
1345 }
1346
1347 ret->methodState = METHOD_DONE;
1348 ret->decision = DECISION_FAIL;
1349 } else if (tlv.result == TEAP_STATUS_SUCCESS) {
1350 tmp = eap_teap_tlv_result(TEAP_STATUS_SUCCESS, 0);
1351 resp = wpabuf_concat(tmp, resp);
1352 }
1353 if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
1354 tlv.iresult == TEAP_STATUS_FAILURE) && !iresult_added) {
1355 tmp = eap_teap_tlv_result((!failed && data->phase2_success) ?
1356 TEAP_STATUS_SUCCESS :
1357 TEAP_STATUS_FAILURE, 1);
1358 resp = wpabuf_concat(tmp, resp);
1359 }
1360
1361 if (resp && tlv.result == TEAP_STATUS_SUCCESS && !failed &&
1362 tlv.crypto_binding && data->phase2_success) {
1363 /* Successfully completed Phase 2 */
1364 wpa_printf(MSG_DEBUG,
1365 "EAP-TEAP: Authentication completed successfully");
1366 ret->methodState = METHOD_MAY_CONT;
1367 data->on_tx_completion = data->provisioning ?
1368 METHOD_MAY_CONT : METHOD_DONE;
1369 ret->decision = DECISION_UNCOND_SUCC;
1370 }
1371
1372 if (!resp) {
1373 wpa_printf(MSG_DEBUG,
1374 "EAP-TEAP: No recognized TLVs - send empty response packet");
1375 resp = wpabuf_alloc(1);
1376 }
1377
1378 send_resp:
1379 if (!resp)
1380 return 0;
1381
1382 wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: Encrypting Phase 2 data", resp);
1383 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
1384 data->teap_version, identifier,
1385 resp, out_data)) {
1386 wpa_printf(MSG_INFO,
1387 "EAP-TEAP: Failed to encrypt a Phase 2 frame");
1388 }
1389 wpabuf_free(resp);
1390
1391 return 0;
1392 }
1393
1394
1395 static int eap_teap_decrypt(struct eap_sm *sm, struct eap_teap_data *data,
1396 struct eap_method_ret *ret, u8 identifier,
1397 const struct wpabuf *in_data,
1398 struct wpabuf **out_data)
1399 {
1400 struct wpabuf *in_decrypted;
1401 int res;
1402
1403 wpa_printf(MSG_DEBUG,
1404 "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
1405 (unsigned long) wpabuf_len(in_data));
1406
1407 if (data->pending_phase2_req) {
1408 wpa_printf(MSG_DEBUG,
1409 "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
1410 /* Clear TLS reassembly state. */
1411 eap_peer_tls_reset_input(&data->ssl);
1412
1413 in_decrypted = data->pending_phase2_req;
1414 data->pending_phase2_req = NULL;
1415 goto continue_req;
1416 }
1417
1418 if (wpabuf_len(in_data) == 0) {
1419 /* Received TLS ACK - requesting more fragments */
1420 res = eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
1421 data->teap_version,
1422 identifier, NULL, out_data);
1423 if (res == 0 && !data->ssl.tls_out &&
1424 data->on_tx_completion) {
1425 wpa_printf(MSG_DEBUG,
1426 "EAP-TEAP: Mark authentication completed at full TX of fragments");
1427 ret->methodState = data->on_tx_completion;
1428 data->on_tx_completion = 0;
1429 ret->decision = DECISION_UNCOND_SUCC;
1430 }
1431 return res;
1432 }
1433
1434 res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
1435 if (res)
1436 return res;
1437
1438 continue_req:
1439 wpa_hexdump_buf(MSG_MSGDUMP, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
1440 in_decrypted);
1441
1442 if (wpabuf_len(in_decrypted) < 4) {
1443 wpa_printf(MSG_INFO,
1444 "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
1445 (unsigned long) wpabuf_len(in_decrypted));
1446 wpabuf_free(in_decrypted);
1447 return -1;
1448 }
1449
1450 res = eap_teap_process_decrypted(sm, data, ret, identifier,
1451 in_decrypted, out_data);
1452
1453 wpabuf_free(in_decrypted);
1454
1455 return res;
1456 }
1457
1458
1459 static void eap_teap_select_pac(struct eap_teap_data *data,
1460 const u8 *a_id, size_t a_id_len)
1461 {
1462 if (!a_id)
1463 return;
1464 data->current_pac = eap_teap_get_pac(data->pac, a_id, a_id_len,
1465 PAC_TYPE_TUNNEL_PAC);
1466 if (data->current_pac) {
1467 wpa_printf(MSG_DEBUG,
1468 "EAP-TEAP: PAC found for this A-ID (PAC-Type %d)",
1469 data->current_pac->pac_type);
1470 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TEAP: A-ID-Info",
1471 data->current_pac->a_id_info,
1472 data->current_pac->a_id_info_len);
1473 }
1474 }
1475
1476
1477 static int eap_teap_use_pac_opaque(struct eap_sm *sm,
1478 struct eap_teap_data *data,
1479 struct eap_teap_pac *pac)
1480 {
1481 u8 *tlv;
1482 size_t tlv_len, olen;
1483 struct teap_tlv_hdr *ehdr;
1484
1485 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC-Opaque TLS extension");
1486 olen = pac->pac_opaque_len;
1487 tlv_len = sizeof(*ehdr) + olen;
1488 tlv = os_malloc(tlv_len);
1489 if (tlv) {
1490 ehdr = (struct teap_tlv_hdr *) tlv;
1491 ehdr->tlv_type = host_to_be16(PAC_TYPE_PAC_OPAQUE);
1492 ehdr->length = host_to_be16(olen);
1493 os_memcpy(ehdr + 1, pac->pac_opaque, olen);
1494 }
1495 if (!tlv ||
1496 tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn,
1497 TLS_EXT_PAC_OPAQUE,
1498 tlv, tlv_len) < 0) {
1499 wpa_printf(MSG_DEBUG,
1500 "EAP-TEAP: Failed to add PAC-Opaque TLS extension");
1501 os_free(tlv);
1502 return -1;
1503 }
1504 os_free(tlv);
1505
1506 return 0;
1507 }
1508
1509
1510 static int eap_teap_clear_pac_opaque_ext(struct eap_sm *sm,
1511 struct eap_teap_data *data)
1512 {
1513 if (tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn,
1514 TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) {
1515 wpa_printf(MSG_DEBUG,
1516 "EAP-TEAP: Failed to remove PAC-Opaque TLS extension");
1517 return -1;
1518 }
1519 return 0;
1520 }
1521
1522
1523 static int eap_teap_process_start(struct eap_sm *sm,
1524 struct eap_teap_data *data, u8 flags,
1525 const u8 *pos, size_t left)
1526 {
1527 const u8 *a_id = NULL;
1528 size_t a_id_len = 0;
1529
1530 /* TODO: Support (mostly theoretical) case of TEAP/Start request being
1531 * fragmented */
1532
1533 /* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
1534 data->received_version = flags & EAP_TLS_VERSION_MASK;
1535 wpa_printf(MSG_DEBUG, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
1536 data->received_version, data->teap_version);
1537 if (data->received_version < 1) {
1538 /* Version 1 was the first defined version, so reject 0 */
1539 wpa_printf(MSG_INFO,
1540 "EAP-TEAP: Server used unknown TEAP version %u",
1541 data->received_version);
1542 return -1;
1543 }
1544 if (data->received_version < data->teap_version)
1545 data->teap_version = data->received_version;
1546 wpa_printf(MSG_DEBUG, "EAP-TEAP: Using TEAP version %d",
1547 data->teap_version);
1548 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message payload", pos, left);
1549
1550 /* Parse Authority-ID TLV from Outer TLVs, if present */
1551 if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
1552 const u8 *outer_pos, *outer_end;
1553 u32 outer_tlv_len;
1554
1555 if (left < 4) {
1556 wpa_printf(MSG_INFO,
1557 "EAP-TEAP: Not enough room for the Outer TLV Length field");
1558 return -1;
1559 }
1560
1561 outer_tlv_len = WPA_GET_BE32(pos);
1562 pos += 4;
1563 left -= 4;
1564
1565 if (outer_tlv_len > left) {
1566 wpa_printf(MSG_INFO,
1567 "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
1568 outer_tlv_len, (unsigned int) left);
1569 return -1;
1570 }
1571
1572 outer_pos = pos + left - outer_tlv_len;
1573 outer_end = outer_pos + outer_tlv_len;
1574 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message Outer TLVs",
1575 outer_pos, outer_tlv_len);
1576 wpabuf_free(data->server_outer_tlvs);
1577 data->server_outer_tlvs = wpabuf_alloc_copy(outer_pos,
1578 outer_tlv_len);
1579 if (!data->server_outer_tlvs)
1580 return -1;
1581 left -= outer_tlv_len;
1582 if (left > 0) {
1583 wpa_hexdump(MSG_INFO,
1584 "EAP-TEAP: Unexpected TLS Data in Start message",
1585 pos, left);
1586 return -1;
1587 }
1588
1589 while (outer_pos < outer_end) {
1590 u16 tlv_type, tlv_len;
1591
1592 if (outer_end - outer_pos < 4) {
1593 wpa_printf(MSG_INFO,
1594 "EAP-TEAP: Truncated Outer TLV header");
1595 return -1;
1596 }
1597 tlv_type = WPA_GET_BE16(outer_pos);
1598 outer_pos += 2;
1599 tlv_len = WPA_GET_BE16(outer_pos);
1600 outer_pos += 2;
1601 /* Outer TLVs are required to be optional, so no need to
1602 * check the M flag */
1603 tlv_type &= TEAP_TLV_TYPE_MASK;
1604 wpa_printf(MSG_DEBUG,
1605 "EAP-TEAP: Outer TLV: Type=%u Length=%u",
1606 tlv_type, tlv_len);
1607 if (outer_end - outer_pos < tlv_len) {
1608 wpa_printf(MSG_INFO,
1609 "EAP-TEAP: Truncated Outer TLV (Type %u)",
1610 tlv_type);
1611 return -1;
1612 }
1613 if (tlv_type == TEAP_TLV_AUTHORITY_ID) {
1614 wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Authority-ID",
1615 outer_pos, tlv_len);
1616 if (a_id) {
1617 wpa_printf(MSG_INFO,
1618 "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
1619 return -1;
1620 }
1621 a_id = outer_pos;
1622 a_id_len = tlv_len;
1623 } else {
1624 wpa_printf(MSG_DEBUG,
1625 "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
1626 tlv_type);
1627 }
1628 outer_pos += tlv_len;
1629 }
1630 } else if (left > 0) {
1631 wpa_hexdump(MSG_INFO,
1632 "EAP-TEAP: Unexpected TLS Data in Start message",
1633 pos, left);
1634 return -1;
1635 }
1636
1637 eap_teap_select_pac(data, a_id, a_id_len);
1638
1639 if (data->resuming && data->current_pac) {
1640 wpa_printf(MSG_DEBUG,
1641 "EAP-TEAP: Trying to resume session - do not add PAC-Opaque to TLS ClientHello");
1642 if (eap_teap_clear_pac_opaque_ext(sm, data) < 0)
1643 return -1;
1644 } else if (data->current_pac) {
1645 /*
1646 * PAC found for the A-ID and we are not resuming an old
1647 * session, so add PAC-Opaque extension to ClientHello.
1648 */
1649 if (eap_teap_use_pac_opaque(sm, data, data->current_pac) < 0)
1650 return -1;
1651 } else if (data->provisioning_allowed) {
1652 wpa_printf(MSG_DEBUG,
1653 "EAP-TEAP: No PAC found - starting provisioning");
1654 if (eap_teap_clear_pac_opaque_ext(sm, data) < 0)
1655 return -1;
1656 data->provisioning = 1;
1657 }
1658
1659 return 0;
1660 }
1661
1662
1663 #ifdef CONFIG_TESTING_OPTIONS
1664 static struct wpabuf * eap_teap_add_dummy_outer_tlvs(struct eap_teap_data *data,
1665 struct wpabuf *resp)
1666 {
1667 struct wpabuf *resp2;
1668 u16 len;
1669 const u8 *pos;
1670 u8 flags;
1671
1672 wpabuf_free(data->peer_outer_tlvs);
1673 data->peer_outer_tlvs = wpabuf_alloc(4 + 4);
1674 if (!data->peer_outer_tlvs) {
1675 wpabuf_free(resp);
1676 return NULL;
1677 }
1678
1679 /* Outer TLVs (dummy Vendor-Specific TLV for testing) */
1680 wpabuf_put_be16(data->peer_outer_tlvs, TEAP_TLV_VENDOR_SPECIFIC);
1681 wpabuf_put_be16(data->peer_outer_tlvs, 4);
1682 wpabuf_put_be32(data->peer_outer_tlvs, EAP_VENDOR_HOSTAP);
1683 wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
1684 data->peer_outer_tlvs);
1685
1686 wpa_hexdump_buf(MSG_DEBUG,
1687 "EAP-TEAP: TEAP/Start response before modification",
1688 resp);
1689 resp2 = wpabuf_alloc(wpabuf_len(resp) + 4 +
1690 wpabuf_len(data->peer_outer_tlvs));
1691 if (!resp2) {
1692 wpabuf_free(resp);
1693 return NULL;
1694 }
1695
1696 pos = wpabuf_head(resp);
1697 wpabuf_put_u8(resp2, *pos++); /* Code */
1698 wpabuf_put_u8(resp2, *pos++); /* Identifier */
1699 len = WPA_GET_BE16(pos);
1700 pos += 2;
1701 wpabuf_put_be16(resp2, len + 4 + wpabuf_len(data->peer_outer_tlvs));
1702 wpabuf_put_u8(resp2, *pos++); /* Type */
1703 /* Flags | Ver (with Outer TLV length included flag set to 1) */
1704 flags = *pos++;
1705 if (flags & (EAP_TEAP_FLAGS_OUTER_TLV_LEN |
1706 EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
1707 wpa_printf(MSG_INFO,
1708 "EAP-TEAP: Cannot add Outer TLVs for testing");
1709 wpabuf_free(resp);
1710 wpabuf_free(resp2);
1711 return NULL;
1712 }
1713 flags |= EAP_TEAP_FLAGS_OUTER_TLV_LEN;
1714 wpabuf_put_u8(resp2, flags);
1715 /* Outer TLV Length */
1716 wpabuf_put_be32(resp2, wpabuf_len(data->peer_outer_tlvs));
1717 /* TLS Data */
1718 wpabuf_put_data(resp2, pos, wpabuf_len(resp) - 6);
1719 wpabuf_put_buf(resp2, data->peer_outer_tlvs); /* Outer TLVs */
1720
1721 wpabuf_free(resp);
1722 wpa_hexdump_buf(MSG_DEBUG,
1723 "EAP-TEAP: TEAP/Start response after modification",
1724 resp2);
1725 return resp2;
1726 }
1727 #endif /* CONFIG_TESTING_OPTIONS */
1728
1729
1730 static struct wpabuf * eap_teap_process(struct eap_sm *sm, void *priv,
1731 struct eap_method_ret *ret,
1732 const struct wpabuf *reqData)
1733 {
1734 const struct eap_hdr *req;
1735 size_t left;
1736 int res;
1737 u8 flags, id;
1738 struct wpabuf *resp;
1739 const u8 *pos;
1740 struct eap_teap_data *data = priv;
1741 struct wpabuf msg;
1742
1743 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TEAP, ret,
1744 reqData, &left, &flags);
1745 if (!pos)
1746 return NULL;
1747
1748 req = wpabuf_head(reqData);
1749 id = req->identifier;
1750
1751 if (flags & EAP_TLS_FLAGS_START) {
1752 if (eap_teap_process_start(sm, data, flags, pos, left) < 0)
1753 return NULL;
1754
1755 /* Outer TLVs are not used in further packet processing and
1756 * there cannot be TLS Data in this TEAP/Start message, so
1757 * enforce that by ignoring whatever data might remain in the
1758 * buffer. */
1759 left = 0;
1760 } else if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
1761 /* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
1762 * Outer TLVs MUST be ignored instead of ignoring the full
1763 * message. */
1764 wpa_printf(MSG_INFO,
1765 "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
1766 return NULL;
1767 }
1768
1769 wpabuf_set(&msg, pos, left);
1770
1771 resp = NULL;
1772 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1773 !data->resuming) {
1774 /* Process tunneled (encrypted) phase 2 data. */
1775 res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
1776 if (res < 0) {
1777 ret->methodState = METHOD_DONE;
1778 ret->decision = DECISION_FAIL;
1779 /*
1780 * Ack possible Alert that may have caused failure in
1781 * decryption.
1782 */
1783 res = 1;
1784 }
1785 } else {
1786 if (sm->waiting_ext_cert_check && data->pending_resp) {
1787 struct eap_peer_config *config = eap_get_config(sm);
1788
1789 if (config->pending_ext_cert_check ==
1790 EXT_CERT_CHECK_GOOD) {
1791 wpa_printf(MSG_DEBUG,
1792 "EAP-TEAP: External certificate check succeeded - continue handshake");
1793 resp = data->pending_resp;
1794 data->pending_resp = NULL;
1795 sm->waiting_ext_cert_check = 0;
1796 return resp;
1797 }
1798
1799 if (config->pending_ext_cert_check ==
1800 EXT_CERT_CHECK_BAD) {
1801 wpa_printf(MSG_DEBUG,
1802 "EAP-TEAP: External certificate check failed - force authentication failure");
1803 ret->methodState = METHOD_DONE;
1804 ret->decision = DECISION_FAIL;
1805 sm->waiting_ext_cert_check = 0;
1806 return NULL;
1807 }
1808
1809 wpa_printf(MSG_DEBUG,
1810 "EAP-TEAP: Continuing to wait external server certificate validation");
1811 return NULL;
1812 }
1813
1814 /* Continue processing TLS handshake (phase 1). */
1815 res = eap_peer_tls_process_helper(sm, &data->ssl,
1816 EAP_TYPE_TEAP,
1817 data->teap_version, id, &msg,
1818 &resp);
1819 if (res < 0) {
1820 wpa_printf(MSG_DEBUG,
1821 "EAP-TEAP: TLS processing failed");
1822 ret->methodState = METHOD_DONE;
1823 ret->decision = DECISION_FAIL;
1824 return resp;
1825 }
1826
1827 if (sm->waiting_ext_cert_check) {
1828 wpa_printf(MSG_DEBUG,
1829 "EAP-TEAP: Waiting external server certificate validation");
1830 wpabuf_free(data->pending_resp);
1831 data->pending_resp = resp;
1832 return NULL;
1833 }
1834
1835 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1836 char cipher[80];
1837
1838 wpa_printf(MSG_DEBUG,
1839 "EAP-TEAP: TLS done, proceed to Phase 2");
1840 data->tls_cs =
1841 tls_connection_get_cipher_suite(data->ssl.conn);
1842 wpa_printf(MSG_DEBUG,
1843 "EAP-TEAP: TLS cipher suite 0x%04x",
1844 data->tls_cs);
1845
1846 if (data->provisioning &&
1847 (!(data->provisioning_allowed &
1848 EAP_TEAP_PROV_AUTH) ||
1849 tls_get_cipher(sm->ssl_ctx, data->ssl.conn,
1850 cipher, sizeof(cipher)) < 0 ||
1851 os_strstr(cipher, "ADH-") ||
1852 os_strstr(cipher, "anon"))) {
1853 wpa_printf(MSG_DEBUG,
1854 "EAP-TEAP: Using anonymous (unauthenticated) provisioning");
1855 data->anon_provisioning = 1;
1856 } else {
1857 data->anon_provisioning = 0;
1858 }
1859 data->resuming = 0;
1860 if (eap_teap_derive_key_auth(sm, data) < 0) {
1861 wpa_printf(MSG_DEBUG,
1862 "EAP-TEAP: Could not derive keys");
1863 ret->methodState = METHOD_DONE;
1864 ret->decision = DECISION_FAIL;
1865 wpabuf_free(resp);
1866 return NULL;
1867 }
1868 }
1869
1870 if (res == 2) {
1871 /*
1872 * Application data included in the handshake message.
1873 */
1874 wpabuf_free(data->pending_phase2_req);
1875 data->pending_phase2_req = resp;
1876 resp = NULL;
1877 res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
1878 }
1879 }
1880
1881 if (res == 1) {
1882 wpabuf_free(resp);
1883 return eap_peer_tls_build_ack(id, EAP_TYPE_TEAP,
1884 data->teap_version);
1885 }
1886
1887 #ifdef CONFIG_TESTING_OPTIONS
1888 if (data->test_outer_tlvs && res == 0 && resp &&
1889 (flags & EAP_TLS_FLAGS_START) && wpabuf_len(resp) >= 6)
1890 resp = eap_teap_add_dummy_outer_tlvs(data, resp);
1891 #endif /* CONFIG_TESTING_OPTIONS */
1892
1893 return resp;
1894 }
1895
1896
1897 #if 0 /* TODO */
1898 static Boolean eap_teap_has_reauth_data(struct eap_sm *sm, void *priv)
1899 {
1900 struct eap_teap_data *data = priv;
1901
1902 return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
1903 }
1904
1905
1906 static void eap_teap_deinit_for_reauth(struct eap_sm *sm, void *priv)
1907 {
1908 struct eap_teap_data *data = priv;
1909
1910 if (data->phase2_priv && data->phase2_method &&
1911 data->phase2_method->deinit_for_reauth)
1912 data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
1913 eap_teap_clear(data);
1914 }
1915
1916
1917 static void * eap_teap_init_for_reauth(struct eap_sm *sm, void *priv)
1918 {
1919 struct eap_teap_data *data = priv;
1920
1921 if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1922 eap_teap_deinit(sm, data);
1923 return NULL;
1924 }
1925 if (data->phase2_priv && data->phase2_method &&
1926 data->phase2_method->init_for_reauth)
1927 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1928 data->phase2_success = 0;
1929 data->inner_method_done = 0;
1930 data->result_success_done = 0;
1931 data->done_on_tx_completion = 0;
1932 data->resuming = 1;
1933 data->provisioning = 0;
1934 data->anon_provisioning = 0;
1935 data->simck_idx = 0;
1936 return priv;
1937 }
1938 #endif
1939
1940
1941 static int eap_teap_get_status(struct eap_sm *sm, void *priv, char *buf,
1942 size_t buflen, int verbose)
1943 {
1944 struct eap_teap_data *data = priv;
1945 int len, ret;
1946
1947 len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1948 if (data->phase2_method) {
1949 ret = os_snprintf(buf + len, buflen - len,
1950 "EAP-TEAP Phase 2 method=%s\n",
1951 data->phase2_method->name);
1952 if (os_snprintf_error(buflen - len, ret))
1953 return len;
1954 len += ret;
1955 }
1956 return len;
1957 }
1958
1959
1960 static Boolean eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv)
1961 {
1962 struct eap_teap_data *data = priv;
1963
1964 return data->success;
1965 }
1966
1967
1968 static u8 * eap_teap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1969 {
1970 struct eap_teap_data *data = priv;
1971 u8 *key;
1972
1973 if (!data->success)
1974 return NULL;
1975
1976 key = os_memdup(data->key_data, EAP_TEAP_KEY_LEN);
1977 if (!key)
1978 return NULL;
1979
1980 *len = EAP_TEAP_KEY_LEN;
1981
1982 return key;
1983 }
1984
1985
1986 static u8 * eap_teap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1987 {
1988 struct eap_teap_data *data = priv;
1989 u8 *id;
1990
1991 if (!data->success || !data->session_id)
1992 return NULL;
1993
1994 id = os_memdup(data->session_id, data->id_len);
1995 if (!id)
1996 return NULL;
1997
1998 *len = data->id_len;
1999
2000 return id;
2001 }
2002
2003
2004 static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
2005 {
2006 struct eap_teap_data *data = priv;
2007 u8 *key;
2008
2009 if (!data->success)
2010 return NULL;
2011
2012 key = os_memdup(data->emsk, EAP_EMSK_LEN);
2013 if (!key)
2014 return NULL;
2015
2016 *len = EAP_EMSK_LEN;
2017
2018 return key;
2019 }
2020
2021
2022 int eap_peer_teap_register(void)
2023 {
2024 struct eap_method *eap;
2025
2026 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
2027 EAP_VENDOR_IETF, EAP_TYPE_TEAP, "TEAP");
2028 if (!eap)
2029 return -1;
2030
2031 eap->init = eap_teap_init;
2032 eap->deinit = eap_teap_deinit;
2033 eap->process = eap_teap_process;
2034 eap->isKeyAvailable = eap_teap_isKeyAvailable;
2035 eap->getKey = eap_teap_getKey;
2036 eap->getSessionId = eap_teap_get_session_id;
2037 eap->get_status = eap_teap_get_status;
2038 #if 0 /* TODO */
2039 eap->has_reauth_data = eap_teap_has_reauth_data;
2040 eap->deinit_for_reauth = eap_teap_deinit_for_reauth;
2041 eap->init_for_reauth = eap_teap_init_for_reauth;
2042 #endif
2043 eap->get_emsk = eap_teap_get_emsk;
2044
2045 return eap_peer_method_register(eap);
2046 }