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