xref: /dragonfly/contrib/wpa_supplicant/src/eap_peer/eap_teap.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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