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