LCOV - code coverage report
Current view: top level - src/eap_peer - eap.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 1047 1257 83.3 %
Date: 2015-09-27 Functions: 96 102 94.1 %

          Line data    Source code
       1             : /*
       2             :  * EAP peer state machines (RFC 4137)
       3             :  * Copyright (c) 2004-2014, 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             :  * This file implements the Peer State Machine as defined in RFC 4137. The used
       9             :  * states and state transitions match mostly with the RFC. However, there are
      10             :  * couple of additional transitions for working around small issues noticed
      11             :  * during testing. These exceptions are explained in comments within the
      12             :  * functions in this file. The method functions, m.func(), are similar to the
      13             :  * ones used in RFC 4137, but some small changes have used here to optimize
      14             :  * operations and to add functionality needed for fast re-authentication
      15             :  * (session resumption).
      16             :  */
      17             : 
      18             : #include "includes.h"
      19             : 
      20             : #include "common.h"
      21             : #include "pcsc_funcs.h"
      22             : #include "state_machine.h"
      23             : #include "ext_password.h"
      24             : #include "crypto/crypto.h"
      25             : #include "crypto/tls.h"
      26             : #include "crypto/sha256.h"
      27             : #include "common/wpa_ctrl.h"
      28             : #include "eap_common/eap_wsc_common.h"
      29             : #include "eap_i.h"
      30             : #include "eap_config.h"
      31             : 
      32             : #define STATE_MACHINE_DATA struct eap_sm
      33             : #define STATE_MACHINE_DEBUG_PREFIX "EAP"
      34             : 
      35             : #define EAP_MAX_AUTH_ROUNDS 50
      36             : #define EAP_CLIENT_TIMEOUT_DEFAULT 60
      37             : 
      38             : 
      39             : static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
      40             :                                   EapType method);
      41             : static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id);
      42             : static void eap_sm_processIdentity(struct eap_sm *sm,
      43             :                                    const struct wpabuf *req);
      44             : static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req);
      45             : static struct wpabuf * eap_sm_buildNotify(int id);
      46             : static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
      47             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
      48             : static const char * eap_sm_method_state_txt(EapMethodState state);
      49             : static const char * eap_sm_decision_txt(EapDecision decision);
      50             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
      51             : 
      52             : 
      53             : 
      54      428746 : static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var)
      55             : {
      56      428746 :         return sm->eapol_cb->get_bool(sm->eapol_ctx, var);
      57             : }
      58             : 
      59             : 
      60       78567 : static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,
      61             :                            Boolean value)
      62             : {
      63       78567 :         sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);
      64       78567 : }
      65             : 
      66             : 
      67       66042 : static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var)
      68             : {
      69       66042 :         return sm->eapol_cb->get_int(sm->eapol_ctx, var);
      70             : }
      71             : 
      72             : 
      73       69151 : static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var,
      74             :                           unsigned int value)
      75             : {
      76       69151 :         sm->eapol_cb->set_int(sm->eapol_ctx, var, value);
      77       69151 : }
      78             : 
      79             : 
      80       15075 : static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
      81             : {
      82       15075 :         return sm->eapol_cb->get_eapReqData(sm->eapol_ctx);
      83             : }
      84             : 
      85             : 
      86        5354 : static void eap_notify_status(struct eap_sm *sm, const char *status,
      87             :                                       const char *parameter)
      88             : {
      89        5354 :         wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
      90             :                    status, parameter);
      91        5354 :         if (sm->eapol_cb->notify_status)
      92        5354 :                 sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
      93        5354 : }
      94             : 
      95             : 
      96       47522 : static void eap_sm_free_key(struct eap_sm *sm)
      97             : {
      98       47522 :         if (sm->eapKeyData) {
      99         886 :                 bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
     100         886 :                 sm->eapKeyData = NULL;
     101             :         }
     102       47522 : }
     103             : 
     104             : 
     105       26467 : static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
     106             : {
     107       26467 :         ext_password_free(sm->ext_pw_buf);
     108       26467 :         sm->ext_pw_buf = NULL;
     109             : 
     110       26467 :         if (sm->m == NULL || sm->eap_method_priv == NULL)
     111       51431 :                 return;
     112             : 
     113        3006 :         wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method "
     114        3006 :                    "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt);
     115        1503 :         sm->m->deinit(sm, sm->eap_method_priv);
     116        1503 :         sm->eap_method_priv = NULL;
     117        1503 :         sm->m = NULL;
     118             : }
     119             : 
     120             : 
     121             : /**
     122             :  * eap_allowed_method - Check whether EAP method is allowed
     123             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     124             :  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
     125             :  * @method: EAP type
     126             :  * Returns: 1 = allowed EAP method, 0 = not allowed
     127             :  */
     128        5030 : int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
     129             : {
     130        5030 :         struct eap_peer_config *config = eap_get_config(sm);
     131             :         int i;
     132             :         struct eap_method_type *m;
     133             : 
     134        5030 :         if (config == NULL || config->eap_methods == NULL)
     135           0 :                 return 1;
     136             : 
     137        5030 :         m = config->eap_methods;
     138       21222 :         for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
     139       11162 :                      m[i].method != EAP_TYPE_NONE; i++) {
     140        5031 :                 if (m[i].vendor == vendor && m[i].method == method)
     141        1718 :                         return 1;
     142             :         }
     143        3312 :         return 0;
     144             : }
     145             : 
     146             : 
     147             : /*
     148             :  * This state initializes state machine variables when the machine is
     149             :  * activated (portEnabled = TRUE). This is also used when re-starting
     150             :  * authentication (eapRestart == TRUE).
     151             :  */
     152        3358 : SM_STATE(EAP, INITIALIZE)
     153             : {
     154        3358 :         SM_ENTRY(EAP, INITIALIZE);
     155        3461 :         if (sm->fast_reauth && sm->m && sm->m->has_reauth_data &&
     156         192 :             sm->m->has_reauth_data(sm, sm->eap_method_priv) &&
     157         178 :             !sm->prev_failure &&
     158          89 :             sm->last_config == eap_get_config(sm)) {
     159          83 :                 wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for "
     160             :                            "fast reauthentication");
     161          83 :                 sm->m->deinit_for_reauth(sm, sm->eap_method_priv);
     162             :         } else {
     163        3275 :                 sm->last_config = eap_get_config(sm);
     164        3275 :                 eap_deinit_prev_method(sm, "INITIALIZE");
     165             :         }
     166        3358 :         sm->selectedMethod = EAP_TYPE_NONE;
     167        3358 :         sm->methodState = METHOD_NONE;
     168        3358 :         sm->allowNotifications = TRUE;
     169        3358 :         sm->decision = DECISION_FAIL;
     170        3358 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
     171        3358 :         eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
     172        3358 :         eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
     173        3358 :         eapol_set_bool(sm, EAPOL_eapFail, FALSE);
     174        3358 :         eap_sm_free_key(sm);
     175        3358 :         os_free(sm->eapSessionId);
     176        3358 :         sm->eapSessionId = NULL;
     177        3358 :         sm->eapKeyAvailable = FALSE;
     178        3358 :         eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
     179        3358 :         sm->lastId = -1; /* new session - make sure this does not match with
     180             :                           * the first EAP-Packet */
     181             :         /*
     182             :          * RFC 4137 does not reset eapResp and eapNoResp here. However, this
     183             :          * seemed to be able to trigger cases where both were set and if EAPOL
     184             :          * state machine uses eapNoResp first, it may end up not sending a real
     185             :          * reply correctly. This occurred when the workaround in FAIL state set
     186             :          * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
     187             :          * something else(?)
     188             :          */
     189        3358 :         eapol_set_bool(sm, EAPOL_eapResp, FALSE);
     190        3358 :         eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
     191        3358 :         sm->num_rounds = 0;
     192        3358 :         sm->prev_failure = 0;
     193        3358 :         sm->expected_failure = 0;
     194        3358 :         sm->reauthInit = FALSE;
     195        3358 :         sm->erp_seq = (u32) -1;
     196        3358 : }
     197             : 
     198             : 
     199             : /*
     200             :  * This state is reached whenever service from the lower layer is interrupted
     201             :  * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE
     202             :  * occurs when the port becomes enabled.
     203             :  */
     204       58994 : SM_STATE(EAP, DISABLED)
     205             : {
     206       58994 :         SM_ENTRY(EAP, DISABLED);
     207       58994 :         sm->num_rounds = 0;
     208             :         /*
     209             :          * RFC 4137 does not describe clearing of idleWhile here, but doing so
     210             :          * allows the timer tick to be stopped more quickly when EAP is not in
     211             :          * use.
     212             :          */
     213       58994 :         eapol_set_int(sm, EAPOL_idleWhile, 0);
     214       58994 : }
     215             : 
     216             : 
     217             : /*
     218             :  * The state machine spends most of its time here, waiting for something to
     219             :  * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and
     220             :  * SEND_RESPONSE states.
     221             :  */
     222       10299 : SM_STATE(EAP, IDLE)
     223             : {
     224       10299 :         SM_ENTRY(EAP, IDLE);
     225       10299 : }
     226             : 
     227             : 
     228             : /*
     229             :  * This state is entered when an EAP packet is received (eapReq == TRUE) to
     230             :  * parse the packet header.
     231             :  */
     232        8323 : SM_STATE(EAP, RECEIVED)
     233             : {
     234             :         const struct wpabuf *eapReqData;
     235             : 
     236        8323 :         SM_ENTRY(EAP, RECEIVED);
     237        8323 :         eapReqData = eapol_get_eapReqData(sm);
     238             :         /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */
     239        8323 :         eap_sm_parseEapReq(sm, eapReqData);
     240        8323 :         sm->num_rounds++;
     241        8323 : }
     242             : 
     243             : 
     244             : /*
     245             :  * This state is entered when a request for a new type comes in. Either the
     246             :  * correct method is started, or a Nak response is built.
     247             :  */
     248        1717 : SM_STATE(EAP, GET_METHOD)
     249             : {
     250             :         int reinit;
     251             :         EapType method;
     252             :         const struct eap_method *eap_method;
     253             : 
     254        1717 :         SM_ENTRY(EAP, GET_METHOD);
     255             : 
     256        1717 :         if (sm->reqMethod == EAP_TYPE_EXPANDED)
     257         426 :                 method = sm->reqVendorMethod;
     258             :         else
     259        1291 :                 method = sm->reqMethod;
     260             : 
     261        1717 :         eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
     262             : 
     263        1717 :         if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
     264         118 :                 wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
     265             :                            sm->reqVendor, method);
     266         118 :                 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
     267             :                         "vendor=%u method=%u -> NAK",
     268             :                         sm->reqVendor, method);
     269         118 :                 eap_notify_status(sm, "refuse proposed method",
     270             :                                   eap_method ?  eap_method->name : "unknown");
     271         118 :                 goto nak;
     272             :         }
     273             : 
     274        1599 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
     275             :                 "vendor=%u method=%u", sm->reqVendor, method);
     276             : 
     277        1599 :         eap_notify_status(sm, "accept proposed method",
     278             :                           eap_method ?  eap_method->name : "unknown");
     279             :         /*
     280             :          * RFC 4137 does not define specific operation for fast
     281             :          * re-authentication (session resumption). The design here is to allow
     282             :          * the previously used method data to be maintained for
     283             :          * re-authentication if the method support session resumption.
     284             :          * Otherwise, the previously used method data is freed and a new method
     285             :          * is allocated here.
     286             :          */
     287        3198 :         if (sm->fast_reauth &&
     288        1729 :             sm->m && sm->m->vendor == sm->reqVendor &&
     289         130 :             sm->m->method == method &&
     290         130 :             sm->m->has_reauth_data &&
     291          65 :             sm->m->has_reauth_data(sm, sm->eap_method_priv)) {
     292          65 :                 wpa_printf(MSG_DEBUG, "EAP: Using previous method data"
     293             :                            " for fast re-authentication");
     294          65 :                 reinit = 1;
     295             :         } else {
     296        1534 :                 eap_deinit_prev_method(sm, "GET_METHOD");
     297        1534 :                 reinit = 0;
     298             :         }
     299             : 
     300        1599 :         sm->selectedMethod = sm->reqMethod;
     301        1599 :         if (sm->m == NULL)
     302        1534 :                 sm->m = eap_method;
     303        1599 :         if (!sm->m) {
     304           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
     305             :                            "vendor %d method %d",
     306             :                            sm->reqVendor, method);
     307           0 :                 goto nak;
     308             :         }
     309             : 
     310        1599 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
     311             : 
     312        1599 :         wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
     313             :                    "vendor %u method %u (%s)",
     314        1599 :                    sm->reqVendor, method, sm->m->name);
     315        1599 :         if (reinit)
     316          65 :                 sm->eap_method_priv = sm->m->init_for_reauth(
     317             :                         sm, sm->eap_method_priv);
     318             :         else
     319        1534 :                 sm->eap_method_priv = sm->m->init(sm);
     320             : 
     321        1599 :         if (sm->eap_method_priv == NULL) {
     322          31 :                 struct eap_peer_config *config = eap_get_config(sm);
     323          31 :                 wpa_msg(sm->msg_ctx, MSG_INFO,
     324             :                         "EAP: Failed to initialize EAP method: vendor %u "
     325             :                         "method %u (%s)",
     326          31 :                         sm->reqVendor, method, sm->m->name);
     327          31 :                 sm->m = NULL;
     328          31 :                 sm->methodState = METHOD_NONE;
     329          31 :                 sm->selectedMethod = EAP_TYPE_NONE;
     330          36 :                 if (sm->reqMethod == EAP_TYPE_TLS && config &&
     331          10 :                     (config->pending_req_pin ||
     332           5 :                      config->pending_req_passphrase)) {
     333             :                         /*
     334             :                          * Return without generating Nak in order to allow
     335             :                          * entering of PIN code or passphrase to retry the
     336             :                          * current EAP packet.
     337             :                          */
     338           5 :                         wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase "
     339             :                                    "request - skip Nak");
     340           5 :                         return;
     341             :                 }
     342             : 
     343          26 :                 goto nak;
     344             :         }
     345             : 
     346        1568 :         sm->methodState = METHOD_INIT;
     347        1568 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD
     348             :                 "EAP vendor %u method %u (%s) selected",
     349        1568 :                 sm->reqVendor, method, sm->m->name);
     350        1568 :         return;
     351             : 
     352             : nak:
     353         144 :         wpabuf_free(sm->eapRespData);
     354         144 :         sm->eapRespData = NULL;
     355         144 :         sm->eapRespData = eap_sm_buildNak(sm, sm->reqId);
     356             : }
     357             : 
     358             : 
     359             : #ifdef CONFIG_ERP
     360             : 
     361          60 : static char * eap_home_realm(struct eap_sm *sm)
     362             : {
     363          60 :         struct eap_peer_config *config = eap_get_config(sm);
     364             :         char *realm;
     365             :         size_t i, realm_len;
     366             : 
     367          60 :         if (!config)
     368           0 :                 return NULL;
     369             : 
     370          60 :         if (config->identity) {
     371         606 :                 for (i = 0; i < config->identity_len; i++) {
     372         606 :                         if (config->identity[i] == '@')
     373          60 :                                 break;
     374             :                 }
     375          60 :                 if (i < config->identity_len) {
     376          60 :                         realm_len = config->identity_len - i - 1;
     377          60 :                         realm = os_malloc(realm_len + 1);
     378          60 :                         if (realm == NULL)
     379           0 :                                 return NULL;
     380          60 :                         os_memcpy(realm, &config->identity[i + 1], realm_len);
     381          60 :                         realm[realm_len] = '\0';
     382          60 :                         return realm;
     383             :                 }
     384             :         }
     385             : 
     386           0 :         if (config->anonymous_identity) {
     387           0 :                 for (i = 0; i < config->anonymous_identity_len; i++) {
     388           0 :                         if (config->anonymous_identity[i] == '@')
     389           0 :                                 break;
     390             :                 }
     391           0 :                 if (i < config->anonymous_identity_len) {
     392           0 :                         realm_len = config->anonymous_identity_len - i - 1;
     393           0 :                         realm = os_malloc(realm_len + 1);
     394           0 :                         if (realm == NULL)
     395           0 :                                 return NULL;
     396           0 :                         os_memcpy(realm, &config->anonymous_identity[i + 1],
     397             :                                   realm_len);
     398           0 :                         realm[realm_len] = '\0';
     399           0 :                         return realm;
     400             :                 }
     401             :         }
     402             : 
     403           0 :         return os_strdup("");
     404             : }
     405             : 
     406             : 
     407             : static struct eap_erp_key *
     408          61 : eap_erp_get_key(struct eap_sm *sm, const char *realm)
     409             : {
     410             :         struct eap_erp_key *erp;
     411             : 
     412          61 :         dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
     413             :                 char *pos;
     414             : 
     415          22 :                 pos = os_strchr(erp->keyname_nai, '@');
     416          22 :                 if (!pos)
     417           0 :                         continue;
     418          22 :                 pos++;
     419          22 :                 if (os_strcmp(pos, realm) == 0)
     420          22 :                         return erp;
     421             :         }
     422             : 
     423          39 :         return NULL;
     424             : }
     425             : 
     426             : 
     427             : static struct eap_erp_key *
     428          21 : eap_erp_get_key_nai(struct eap_sm *sm, const char *nai)
     429             : {
     430             :         struct eap_erp_key *erp;
     431             : 
     432          21 :         dl_list_for_each(erp, &sm->erp_keys, struct eap_erp_key, list) {
     433          21 :                 if (os_strcmp(erp->keyname_nai, nai) == 0)
     434          21 :                         return erp;
     435             :         }
     436             : 
     437           0 :         return NULL;
     438             : }
     439             : 
     440             : 
     441          19 : static void eap_peer_erp_free_key(struct eap_erp_key *erp)
     442             : {
     443          19 :         dl_list_del(&erp->list);
     444          19 :         bin_clear_free(erp, sizeof(*erp));
     445          19 : }
     446             : 
     447             : 
     448          19 : static void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm)
     449             : {
     450             :         struct eap_erp_key *erp;
     451             : 
     452          39 :         while ((erp = eap_erp_get_key(sm, realm)) != NULL) {
     453           1 :                 wpa_printf(MSG_DEBUG, "EAP: Delete old ERP key %s",
     454           1 :                            erp->keyname_nai);
     455           1 :                 eap_peer_erp_free_key(erp);
     456             :         }
     457          19 : }
     458             : 
     459             : #endif /* CONFIG_ERP */
     460             : 
     461             : 
     462         614 : void eap_peer_erp_free_keys(struct eap_sm *sm)
     463             : {
     464             : #ifdef CONFIG_ERP
     465             :         struct eap_erp_key *erp, *tmp;
     466             : 
     467         631 :         dl_list_for_each_safe(erp, tmp, &sm->erp_keys, struct eap_erp_key, list)
     468          17 :                 eap_peer_erp_free_key(erp);
     469             : #endif /* CONFIG_ERP */
     470         614 : }
     471             : 
     472             : 
     473          19 : static void eap_peer_erp_init(struct eap_sm *sm)
     474             : {
     475             : #ifdef CONFIG_ERP
     476          19 :         u8 *emsk = NULL;
     477          19 :         size_t emsk_len = 0;
     478             :         u8 EMSKname[EAP_EMSK_NAME_LEN];
     479             :         u8 len[2];
     480             :         char *realm;
     481             :         size_t realm_len, nai_buf_len;
     482          19 :         struct eap_erp_key *erp = NULL;
     483             :         int pos;
     484             : 
     485          19 :         realm = eap_home_realm(sm);
     486          19 :         if (!realm)
     487          19 :                 return;
     488          19 :         realm_len = os_strlen(realm);
     489          19 :         wpa_printf(MSG_DEBUG, "EAP: Realm for ERP keyName-NAI: %s", realm);
     490          19 :         eap_erp_remove_keys_realm(sm, realm);
     491             : 
     492          19 :         nai_buf_len = 2 * EAP_EMSK_NAME_LEN + 1 + realm_len;
     493          19 :         if (nai_buf_len > 253) {
     494             :                 /*
     495             :                  * keyName-NAI has a maximum length of 253 octet to fit in
     496             :                  * RADIUS attributes.
     497             :                  */
     498           0 :                 wpa_printf(MSG_DEBUG,
     499             :                            "EAP: Too long realm for ERP keyName-NAI maximum length");
     500           0 :                 goto fail;
     501             :         }
     502          19 :         nai_buf_len++; /* null termination */
     503          19 :         erp = os_zalloc(sizeof(*erp) + nai_buf_len);
     504          19 :         if (erp == NULL)
     505           0 :                 goto fail;
     506             : 
     507          19 :         emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
     508          19 :         if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) {
     509           0 :                 wpa_printf(MSG_DEBUG,
     510             :                            "EAP: No suitable EMSK available for ERP");
     511           0 :                 goto fail;
     512             :         }
     513             : 
     514          19 :         wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
     515             : 
     516          19 :         WPA_PUT_BE16(len, 8);
     517          19 :         if (hmac_sha256_kdf(sm->eapSessionId, sm->eapSessionIdLen, "EMSK",
     518             :                             len, sizeof(len),
     519             :                             EMSKname, EAP_EMSK_NAME_LEN) < 0) {
     520           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname");
     521           0 :                 goto fail;
     522             :         }
     523          19 :         wpa_hexdump(MSG_DEBUG, "EAP: EMSKname", EMSKname, EAP_EMSK_NAME_LEN);
     524             : 
     525          19 :         pos = wpa_snprintf_hex(erp->keyname_nai, nai_buf_len,
     526             :                                EMSKname, EAP_EMSK_NAME_LEN);
     527          19 :         erp->keyname_nai[pos] = '@';
     528          19 :         os_memcpy(&erp->keyname_nai[pos + 1], realm, realm_len);
     529             : 
     530          19 :         WPA_PUT_BE16(len, emsk_len);
     531          38 :         if (hmac_sha256_kdf(emsk, emsk_len,
     532             :                             "EAP Re-authentication Root Key@ietf.org",
     533          19 :                             len, sizeof(len), erp->rRK, emsk_len) < 0) {
     534           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not derive rRK for ERP");
     535           0 :                 goto fail;
     536             :         }
     537          19 :         erp->rRK_len = emsk_len;
     538          19 :         wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len);
     539             : 
     540          38 :         if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
     541             :                             "EAP Re-authentication Integrity Key@ietf.org",
     542          19 :                             len, sizeof(len), erp->rIK, erp->rRK_len) < 0) {
     543           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP");
     544           0 :                 goto fail;
     545             :         }
     546          19 :         erp->rIK_len = erp->rRK_len;
     547          19 :         wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rIK", erp->rIK, erp->rIK_len);
     548             : 
     549          19 :         wpa_printf(MSG_DEBUG, "EAP: Stored ERP keys %s", erp->keyname_nai);
     550          19 :         dl_list_add(&sm->erp_keys, &erp->list);
     551          19 :         erp = NULL;
     552             : fail:
     553          19 :         bin_clear_free(emsk, emsk_len);
     554          19 :         bin_clear_free(erp, sizeof(*erp));
     555          19 :         os_free(realm);
     556             : #endif /* CONFIG_ERP */
     557             : }
     558             : 
     559             : 
     560             : #ifdef CONFIG_ERP
     561          41 : static int eap_peer_erp_reauth_start(struct eap_sm *sm,
     562             :                                      const struct eap_hdr *hdr, size_t len)
     563             : {
     564             :         char *realm;
     565             :         struct eap_erp_key *erp;
     566             :         struct wpabuf *msg;
     567             :         u8 hash[SHA256_MAC_LEN];
     568             : 
     569          41 :         realm = eap_home_realm(sm);
     570          41 :         if (!realm)
     571           0 :                 return -1;
     572             : 
     573          41 :         erp = eap_erp_get_key(sm, realm);
     574          41 :         os_free(realm);
     575          41 :         realm = NULL;
     576          41 :         if (!erp)
     577          20 :                 return -1;
     578             : 
     579          21 :         if (erp->next_seq >= 65536)
     580           0 :                 return -1; /* SEQ has range of 0..65535 */
     581             : 
     582             :         /* TODO: check rRK lifetime expiration */
     583             : 
     584          42 :         wpa_printf(MSG_DEBUG, "EAP: Valid ERP key found %s (SEQ=%u)",
     585          21 :                    erp->keyname_nai, erp->next_seq);
     586             : 
     587          42 :         msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
     588          21 :                             1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16,
     589          21 :                             EAP_CODE_INITIATE, hdr->identifier);
     590          21 :         if (msg == NULL)
     591           0 :                 return -1;
     592             : 
     593          21 :         wpabuf_put_u8(msg, 0x20); /* Flags: R=0 B=0 L=1 */
     594          21 :         wpabuf_put_be16(msg, erp->next_seq);
     595             : 
     596          21 :         wpabuf_put_u8(msg, EAP_ERP_TLV_KEYNAME_NAI);
     597          21 :         wpabuf_put_u8(msg, os_strlen(erp->keyname_nai));
     598          21 :         wpabuf_put_str(msg, erp->keyname_nai);
     599             : 
     600          21 :         wpabuf_put_u8(msg, EAP_ERP_CS_HMAC_SHA256_128); /* Cryptosuite */
     601             : 
     602          42 :         if (hmac_sha256(erp->rIK, erp->rIK_len,
     603          21 :                         wpabuf_head(msg), wpabuf_len(msg), hash) < 0) {
     604           0 :                 wpabuf_free(msg);
     605           0 :                 return -1;
     606             :         }
     607          21 :         wpabuf_put_data(msg, hash, 16);
     608             : 
     609          21 :         wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth");
     610          21 :         sm->erp_seq = erp->next_seq;
     611          21 :         erp->next_seq++;
     612          21 :         wpabuf_free(sm->eapRespData);
     613          21 :         sm->eapRespData = msg;
     614          21 :         sm->reauthInit = TRUE;
     615          21 :         return 0;
     616             : }
     617             : #endif /* CONFIG_ERP */
     618             : 
     619             : 
     620             : /*
     621             :  * The method processing happens here. The request from the authenticator is
     622             :  * processed, and an appropriate response packet is built.
     623             :  */
     624        5078 : SM_STATE(EAP, METHOD)
     625             : {
     626             :         struct wpabuf *eapReqData;
     627             :         struct eap_method_ret ret;
     628        5078 :         int min_len = 1;
     629             : 
     630        5078 :         SM_ENTRY(EAP, METHOD);
     631        5078 :         if (sm->m == NULL) {
     632           0 :                 wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected");
     633           0 :                 return;
     634             :         }
     635             : 
     636        5078 :         eapReqData = eapol_get_eapReqData(sm);
     637        5078 :         if (sm->m->vendor == EAP_VENDOR_IETF && sm->m->method == EAP_TYPE_LEAP)
     638          19 :                 min_len = 0; /* LEAP uses EAP-Success without payload */
     639        5078 :         if (!eap_hdr_len_valid(eapReqData, min_len))
     640           0 :                 return;
     641             : 
     642             :         /*
     643             :          * Get ignore, methodState, decision, allowNotifications, and
     644             :          * eapRespData. RFC 4137 uses three separate method procedure (check,
     645             :          * process, and buildResp) in this state. These have been combined into
     646             :          * a single function call to m->process() in order to optimize EAP
     647             :          * method implementation interface a bit. These procedures are only
     648             :          * used from within this METHOD state, so there is no need to keep
     649             :          * these as separate C functions.
     650             :          *
     651             :          * The RFC 4137 procedures return values as follows:
     652             :          * ignore = m.check(eapReqData)
     653             :          * (methodState, decision, allowNotifications) = m.process(eapReqData)
     654             :          * eapRespData = m.buildResp(reqId)
     655             :          */
     656        5078 :         os_memset(&ret, 0, sizeof(ret));
     657        5078 :         ret.ignore = sm->ignore;
     658        5078 :         ret.methodState = sm->methodState;
     659        5078 :         ret.decision = sm->decision;
     660        5078 :         ret.allowNotifications = sm->allowNotifications;
     661        5078 :         wpabuf_free(sm->eapRespData);
     662        5078 :         sm->eapRespData = NULL;
     663        5078 :         sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
     664             :                                          eapReqData);
     665       10156 :         wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
     666             :                    "methodState=%s decision=%s eapRespData=%p",
     667        5078 :                    ret.ignore ? "TRUE" : "FALSE",
     668             :                    eap_sm_method_state_txt(ret.methodState),
     669             :                    eap_sm_decision_txt(ret.decision),
     670             :                    sm->eapRespData);
     671             : 
     672        5078 :         sm->ignore = ret.ignore;
     673        5078 :         if (sm->ignore)
     674          93 :                 return;
     675        4985 :         sm->methodState = ret.methodState;
     676        4985 :         sm->decision = ret.decision;
     677        4985 :         sm->allowNotifications = ret.allowNotifications;
     678             : 
     679        8144 :         if (sm->m->isKeyAvailable && sm->m->getKey &&
     680        3159 :             sm->m->isKeyAvailable(sm, sm->eap_method_priv)) {
     681         866 :                 struct eap_peer_config *config = eap_get_config(sm);
     682             : 
     683         866 :                 eap_sm_free_key(sm);
     684         866 :                 sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
     685             :                                                &sm->eapKeyDataLen);
     686         866 :                 os_free(sm->eapSessionId);
     687         866 :                 sm->eapSessionId = NULL;
     688         866 :                 if (sm->m->getSessionId) {
     689         857 :                         sm->eapSessionId = sm->m->getSessionId(
     690             :                                 sm, sm->eap_method_priv,
     691             :                                 &sm->eapSessionIdLen);
     692        1714 :                         wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
     693         857 :                                     sm->eapSessionId, sm->eapSessionIdLen);
     694             :                 }
     695         866 :                 if (config->erp && sm->m->get_emsk && sm->eapSessionId)
     696          19 :                         eap_peer_erp_init(sm);
     697             :         }
     698             : }
     699             : 
     700             : 
     701             : /*
     702             :  * This state signals the lower layer that a response packet is ready to be
     703             :  * sent.
     704             :  */
     705        6799 : SM_STATE(EAP, SEND_RESPONSE)
     706             : {
     707        6799 :         SM_ENTRY(EAP, SEND_RESPONSE);
     708        6799 :         wpabuf_free(sm->lastRespData);
     709        6799 :         if (sm->eapRespData) {
     710        6721 :                 if (sm->workaround)
     711        6696 :                         os_memcpy(sm->last_sha1, sm->req_sha1, 20);
     712        6721 :                 sm->lastId = sm->reqId;
     713        6721 :                 sm->lastRespData = wpabuf_dup(sm->eapRespData);
     714        6721 :                 eapol_set_bool(sm, EAPOL_eapResp, TRUE);
     715             :         } else {
     716          78 :                 wpa_printf(MSG_DEBUG, "EAP: No eapRespData available");
     717          78 :                 sm->lastRespData = NULL;
     718             :         }
     719        6799 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     720        6799 :         eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
     721        6799 :         sm->reauthInit = FALSE;
     722        6799 : }
     723             : 
     724             : 
     725             : /*
     726             :  * This state signals the lower layer that the request was discarded, and no
     727             :  * response packet will be sent at this time.
     728             :  */
     729         142 : SM_STATE(EAP, DISCARD)
     730             : {
     731         142 :         SM_ENTRY(EAP, DISCARD);
     732         142 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     733         142 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     734         142 : }
     735             : 
     736             : 
     737             : /*
     738             :  * Handles requests for Identity method and builds a response.
     739             :  */
     740        1668 : SM_STATE(EAP, IDENTITY)
     741             : {
     742             :         const struct wpabuf *eapReqData;
     743             : 
     744        1668 :         SM_ENTRY(EAP, IDENTITY);
     745        1668 :         eapReqData = eapol_get_eapReqData(sm);
     746        1668 :         if (!eap_hdr_len_valid(eapReqData, 1))
     747        1668 :                 return;
     748        1668 :         eap_sm_processIdentity(sm, eapReqData);
     749        1668 :         wpabuf_free(sm->eapRespData);
     750        1668 :         sm->eapRespData = NULL;
     751        1668 :         sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0);
     752             : }
     753             : 
     754             : 
     755             : /*
     756             :  * Handles requests for Notification method and builds a response.
     757             :  */
     758           6 : SM_STATE(EAP, NOTIFICATION)
     759             : {
     760             :         const struct wpabuf *eapReqData;
     761             : 
     762           6 :         SM_ENTRY(EAP, NOTIFICATION);
     763           6 :         eapReqData = eapol_get_eapReqData(sm);
     764           6 :         if (!eap_hdr_len_valid(eapReqData, 1))
     765           6 :                 return;
     766           6 :         eap_sm_processNotify(sm, eapReqData);
     767           6 :         wpabuf_free(sm->eapRespData);
     768           6 :         sm->eapRespData = NULL;
     769           6 :         sm->eapRespData = eap_sm_buildNotify(sm->reqId);
     770             : }
     771             : 
     772             : 
     773             : /*
     774             :  * This state retransmits the previous response packet.
     775             :  */
     776          20 : SM_STATE(EAP, RETRANSMIT)
     777             : {
     778          20 :         SM_ENTRY(EAP, RETRANSMIT);
     779          20 :         wpabuf_free(sm->eapRespData);
     780          20 :         if (sm->lastRespData)
     781          20 :                 sm->eapRespData = wpabuf_dup(sm->lastRespData);
     782             :         else
     783           0 :                 sm->eapRespData = NULL;
     784          20 : }
     785             : 
     786             : 
     787             : /*
     788             :  * This state is entered in case of a successful completion of authentication
     789             :  * and state machine waits here until port is disabled or EAP authentication is
     790             :  * restarted.
     791             :  */
     792         730 : SM_STATE(EAP, SUCCESS)
     793             : {
     794         730 :         SM_ENTRY(EAP, SUCCESS);
     795         730 :         if (sm->eapKeyData != NULL)
     796         724 :                 sm->eapKeyAvailable = TRUE;
     797         730 :         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
     798             : 
     799             :         /*
     800             :          * RFC 4137 does not clear eapReq here, but this seems to be required
     801             :          * to avoid processing the same request twice when state machine is
     802             :          * initialized.
     803             :          */
     804         730 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     805             : 
     806             :         /*
     807             :          * RFC 4137 does not set eapNoResp here, but this seems to be required
     808             :          * to get EAPOL Supplicant backend state machine into SUCCESS state. In
     809             :          * addition, either eapResp or eapNoResp is required to be set after
     810             :          * processing the received EAP frame.
     811             :          */
     812         730 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     813             : 
     814         730 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
     815             :                 "EAP authentication completed successfully");
     816         730 : }
     817             : 
     818             : 
     819             : /*
     820             :  * This state is entered in case of a failure and state machine waits here
     821             :  * until port is disabled or EAP authentication is restarted.
     822             :  */
     823         653 : SM_STATE(EAP, FAILURE)
     824             : {
     825         653 :         SM_ENTRY(EAP, FAILURE);
     826         653 :         eapol_set_bool(sm, EAPOL_eapFail, TRUE);
     827             : 
     828             :         /*
     829             :          * RFC 4137 does not clear eapReq here, but this seems to be required
     830             :          * to avoid processing the same request twice when state machine is
     831             :          * initialized.
     832             :          */
     833         653 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
     834             : 
     835             :         /*
     836             :          * RFC 4137 does not set eapNoResp here. However, either eapResp or
     837             :          * eapNoResp is required to be set after processing the received EAP
     838             :          * frame.
     839             :          */
     840         653 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
     841             : 
     842         653 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
     843             :                 "EAP authentication failed");
     844             : 
     845         653 :         sm->prev_failure = 1;
     846         653 : }
     847             : 
     848             : 
     849         136 : static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
     850             : {
     851             :         /*
     852             :          * At least Microsoft IAS and Meetinghouse Aegis seem to be sending
     853             :          * EAP-Success/Failure with lastId + 1 even though RFC 3748 and
     854             :          * RFC 4137 require that reqId == lastId. In addition, it looks like
     855             :          * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
     856             :          *
     857             :          * Accept this kind of Id if EAP workarounds are enabled. These are
     858             :          * unauthenticated plaintext messages, so this should have minimal
     859             :          * security implications (bit easier to fake EAP-Success/Failure).
     860             :          */
     861         144 :         if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||
     862           8 :                                reqId == ((lastId + 2) & 0xff))) {
     863         129 :                 wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "
     864             :                            "identifier field in EAP Success: "
     865             :                            "reqId=%d lastId=%d (these are supposed to be "
     866             :                            "same)", reqId, lastId);
     867         129 :                 return 1;
     868             :         }
     869           7 :         wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "
     870             :                    "lastId=%d", reqId, lastId);
     871           7 :         return 0;
     872             : }
     873             : 
     874             : 
     875             : /*
     876             :  * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions
     877             :  */
     878             : 
     879       41344 : static void eap_peer_sm_step_idle(struct eap_sm *sm)
     880             : {
     881             :         /*
     882             :          * The first three transitions are from RFC 4137. The last two are
     883             :          * local additions to handle special cases with LEAP and PEAP server
     884             :          * not sending EAP-Success in some cases.
     885             :          */
     886       41344 :         if (eapol_get_bool(sm, EAPOL_eapReq))
     887        8323 :                 SM_ENTER(EAP, RECEIVED);
     888       33021 :         else if ((eapol_get_bool(sm, EAPOL_altAccept) &&
     889       33021 :                   sm->decision != DECISION_FAIL) ||
     890       33021 :                  (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
     891           0 :                   sm->decision == DECISION_UNCOND_SUCC))
     892           0 :                 SM_ENTER(EAP, SUCCESS);
     893       66042 :         else if (eapol_get_bool(sm, EAPOL_altReject) ||
     894       33021 :                  (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&
     895       33021 :                   sm->decision != DECISION_UNCOND_SUCC) ||
     896       33021 :                  (eapol_get_bool(sm, EAPOL_altAccept) &&
     897           0 :                   sm->methodState != METHOD_CONT &&
     898           0 :                   sm->decision == DECISION_FAIL))
     899           0 :                 SM_ENTER(EAP, FAILURE);
     900       33085 :         else if (sm->selectedMethod == EAP_TYPE_LEAP &&
     901          66 :                  sm->leap_done && sm->decision != DECISION_FAIL &&
     902           1 :                  sm->methodState == METHOD_DONE)
     903           1 :                 SM_ENTER(EAP, SUCCESS);
     904       34429 :         else if (sm->selectedMethod == EAP_TYPE_PEAP &&
     905        1409 :                  sm->peap_done && sm->decision != DECISION_FAIL &&
     906           0 :                  sm->methodState == METHOD_DONE)
     907           0 :                 SM_ENTER(EAP, SUCCESS);
     908       41344 : }
     909             : 
     910             : 
     911        8322 : static int eap_peer_req_is_duplicate(struct eap_sm *sm)
     912             : {
     913             :         int duplicate;
     914             : 
     915        8322 :         duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
     916        8343 :         if (sm->workaround && duplicate &&
     917          21 :             os_memcmp(sm->req_sha1, sm->last_sha1, 20) != 0) {
     918             :                 /*
     919             :                  * RFC 4137 uses (reqId == lastId) as the only verification for
     920             :                  * duplicate EAP requests. However, this misses cases where the
     921             :                  * AS is incorrectly using the same id again; and
     922             :                  * unfortunately, such implementations exist. Use SHA1 hash as
     923             :                  * an extra verification for the packets being duplicate to
     924             :                  * workaround these issues.
     925             :                  */
     926           1 :                 wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but "
     927             :                            "EAP packets were not identical");
     928           1 :                 wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a "
     929             :                            "duplicate packet");
     930           1 :                 duplicate = 0;
     931             :         }
     932             : 
     933        8322 :         return duplicate;
     934             : }
     935             : 
     936             : 
     937          10 : static int eap_peer_sm_allow_canned(struct eap_sm *sm)
     938             : {
     939          10 :         struct eap_peer_config *config = eap_get_config(sm);
     940             : 
     941          10 :         return config && config->phase1 &&
     942           0 :                 os_strstr(config->phase1, "allow_canned_success=1");
     943             : }
     944             : 
     945             : 
     946        8322 : static void eap_peer_sm_step_received(struct eap_sm *sm)
     947             : {
     948        8322 :         int duplicate = eap_peer_req_is_duplicate(sm);
     949             : 
     950             :         /*
     951             :          * Two special cases below for LEAP are local additions to work around
     952             :          * odd LEAP behavior (EAP-Success in the middle of authentication and
     953             :          * then swapped roles). Other transitions are based on RFC 4137.
     954             :          */
     955        9052 :         if (sm->rxSuccess && sm->decision != DECISION_FAIL &&
     956         734 :             (sm->reqId == sm->lastId ||
     957           4 :              eap_success_workaround(sm, sm->reqId, sm->lastId)))
     958         729 :                 SM_ENTER(EAP, SUCCESS);
     959        7594 :         else if (sm->workaround && sm->lastId == -1 && sm->rxSuccess &&
     960           2 :                  !sm->rxFailure && !sm->rxReq && eap_peer_sm_allow_canned(sm))
     961           0 :                 SM_ENTER(EAP, SUCCESS); /* EAP-Success prior any EAP method */
     962        7597 :         else if (sm->workaround && sm->lastId == -1 && sm->rxFailure &&
     963          12 :                  !sm->rxReq && sm->methodState != METHOD_CONT &&
     964           4 :                  eap_peer_sm_allow_canned(sm))
     965           0 :                 SM_ENTER(EAP, FAILURE); /* EAP-Failure prior any EAP method */
     966        7598 :         else if (sm->workaround && sm->rxSuccess && !sm->rxFailure &&
     967          15 :                  !sm->rxReq && sm->methodState != METHOD_CONT &&
     968           5 :                  eap_peer_sm_allow_canned(sm))
     969           0 :                 SM_ENTER(EAP, SUCCESS); /* EAP-Success after Identity */
     970       15175 :         else if (sm->methodState != METHOD_CONT &&
     971        8187 :                  ((sm->rxFailure &&
     972        7582 :                    sm->decision != DECISION_UNCOND_SUCC) ||
     973        6986 :                   (sm->rxSuccess && sm->decision == DECISION_FAIL &&
     974           5 :                    (sm->selectedMethod != EAP_TYPE_LEAP ||
     975         609 :                     sm->methodState != METHOD_MAY_CONT))) &&
     976         740 :                  (sm->reqId == sm->lastId ||
     977         132 :                   eap_success_workaround(sm, sm->reqId, sm->lastId)))
     978         602 :                 SM_ENTER(EAP, FAILURE);
     979        6991 :         else if (sm->rxReq && duplicate)
     980          20 :                 SM_ENTER(EAP, RETRANSMIT);
     981       13866 :         else if (sm->rxReq && !duplicate &&
     982        6901 :                  sm->reqMethod == EAP_TYPE_NOTIFICATION &&
     983           6 :                  sm->allowNotifications)
     984           6 :                 SM_ENTER(EAP, NOTIFICATION);
     985       13854 :         else if (sm->rxReq && !duplicate &&
     986       10274 :                  sm->selectedMethod == EAP_TYPE_NONE &&
     987        3385 :                  sm->reqMethod == EAP_TYPE_IDENTITY)
     988        1668 :                 SM_ENTER(EAP, IDENTITY);
     989       10518 :         else if (sm->rxReq && !duplicate &&
     990        6938 :                  sm->selectedMethod == EAP_TYPE_NONE &&
     991        3434 :                  sm->reqMethod != EAP_TYPE_IDENTITY &&
     992        1717 :                  sm->reqMethod != EAP_TYPE_NOTIFICATION)
     993        1717 :                 SM_ENTER(EAP, GET_METHOD);
     994        7084 :         else if (sm->rxReq && !duplicate &&
     995        7008 :                  sm->reqMethod == sm->selectedMethod &&
     996        3504 :                  sm->methodState != METHOD_DONE)
     997        3503 :                 SM_ENTER(EAP, METHOD);
     998          84 :         else if (sm->selectedMethod == EAP_TYPE_LEAP &&
     999          13 :                  (sm->rxSuccess || sm->rxResp))
    1000           7 :                 SM_ENTER(EAP, METHOD);
    1001          70 :         else if (sm->reauthInit)
    1002          21 :                 SM_ENTER(EAP, SEND_RESPONSE);
    1003             :         else
    1004          49 :                 SM_ENTER(EAP, DISCARD);
    1005        8322 : }
    1006             : 
    1007             : 
    1008       81024 : static void eap_peer_sm_step_local(struct eap_sm *sm)
    1009             : {
    1010       81024 :         switch (sm->EAP_state) {
    1011             :         case EAP_INITIALIZE:
    1012        3358 :                 SM_ENTER(EAP, IDLE);
    1013        3358 :                 break;
    1014             :         case EAP_DISABLED:
    1015        3294 :                 if (eapol_get_bool(sm, EAPOL_portEnabled) &&
    1016        1647 :                     !sm->force_disabled)
    1017        1647 :                         SM_ENTER(EAP, INITIALIZE);
    1018        1647 :                 break;
    1019             :         case EAP_IDLE:
    1020       41344 :                 eap_peer_sm_step_idle(sm);
    1021       41344 :                 break;
    1022             :         case EAP_RECEIVED:
    1023        8322 :                 eap_peer_sm_step_received(sm);
    1024        8322 :                 break;
    1025             :         case EAP_GET_METHOD:
    1026        1717 :                 if (sm->selectedMethod == sm->reqMethod)
    1027        1568 :                         SM_ENTER(EAP, METHOD);
    1028             :                 else
    1029         149 :                         SM_ENTER(EAP, SEND_RESPONSE);
    1030        1717 :                 break;
    1031             :         case EAP_METHOD:
    1032             :                 /*
    1033             :                  * Note: RFC 4137 uses methodState == DONE && decision == FAIL
    1034             :                  * as the condition. eapRespData == NULL here is used to allow
    1035             :                  * final EAP method response to be sent without having to change
    1036             :                  * all methods to either use methodState MAY_CONT or leaving
    1037             :                  * decision to something else than FAIL in cases where the only
    1038             :                  * expected response is EAP-Failure.
    1039             :                  */
    1040        5078 :                 if (sm->ignore)
    1041          93 :                         SM_ENTER(EAP, DISCARD);
    1042        6110 :                 else if (sm->methodState == METHOD_DONE &&
    1043        1730 :                          sm->decision == DECISION_FAIL && !sm->eapRespData)
    1044          50 :                         SM_ENTER(EAP, FAILURE);
    1045             :                 else
    1046        4935 :                         SM_ENTER(EAP, SEND_RESPONSE);
    1047        5078 :                 break;
    1048             :         case EAP_SEND_RESPONSE:
    1049        6799 :                 SM_ENTER(EAP, IDLE);
    1050        6799 :                 break;
    1051             :         case EAP_DISCARD:
    1052         142 :                 SM_ENTER(EAP, IDLE);
    1053         142 :                 break;
    1054             :         case EAP_IDENTITY:
    1055        1668 :                 SM_ENTER(EAP, SEND_RESPONSE);
    1056        1668 :                 break;
    1057             :         case EAP_NOTIFICATION:
    1058           6 :                 SM_ENTER(EAP, SEND_RESPONSE);
    1059           6 :                 break;
    1060             :         case EAP_RETRANSMIT:
    1061          20 :                 SM_ENTER(EAP, SEND_RESPONSE);
    1062          20 :                 break;
    1063             :         case EAP_SUCCESS:
    1064        7648 :                 break;
    1065             :         case EAP_FAILURE:
    1066        3275 :                 break;
    1067             :         }
    1068       81024 : }
    1069             : 
    1070             : 
    1071      141735 : SM_STEP(EAP)
    1072             : {
    1073             :         /* Global transitions */
    1074      143446 :         if (eapol_get_bool(sm, EAPOL_eapRestart) &&
    1075        1711 :             eapol_get_bool(sm, EAPOL_portEnabled))
    1076        1711 :                 SM_ENTER_GLOBAL(EAP, INITIALIZE);
    1077      140024 :         else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
    1078       58994 :                 SM_ENTER_GLOBAL(EAP, DISABLED);
    1079       81030 :         else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
    1080             :                 /* RFC 4137 does not place any limit on number of EAP messages
    1081             :                  * in an authentication session. However, some error cases have
    1082             :                  * ended up in a state were EAP messages were sent between the
    1083             :                  * peer and server in a loop (e.g., TLS ACK frame in both
    1084             :                  * direction). Since this is quite undesired outcome, limit the
    1085             :                  * total number of EAP round-trips and abort authentication if
    1086             :                  * this limit is exceeded.
    1087             :                  */
    1088           6 :                 if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
    1089           1 :                         wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
    1090             :                                 "authentication rounds - abort",
    1091             :                                 EAP_MAX_AUTH_ROUNDS);
    1092           1 :                         sm->num_rounds++;
    1093           1 :                         SM_ENTER_GLOBAL(EAP, FAILURE);
    1094             :                 }
    1095             :         } else {
    1096             :                 /* Local transitions */
    1097       81024 :                 eap_peer_sm_step_local(sm);
    1098             :         }
    1099      141735 : }
    1100             : 
    1101             : 
    1102        1717 : static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
    1103             :                                   EapType method)
    1104             : {
    1105        1717 :         if (!eap_allowed_method(sm, vendor, method)) {
    1106         118 :                 wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
    1107             :                            "vendor %u method %u", vendor, method);
    1108         118 :                 return FALSE;
    1109             :         }
    1110        1599 :         if (eap_peer_get_eap_method(vendor, method))
    1111        1599 :                 return TRUE;
    1112           0 :         wpa_printf(MSG_DEBUG, "EAP: not included in build: "
    1113             :                    "vendor %u method %u", vendor, method);
    1114           0 :         return FALSE;
    1115             : }
    1116             : 
    1117             : 
    1118           4 : static struct wpabuf * eap_sm_build_expanded_nak(
    1119             :         struct eap_sm *sm, int id, const struct eap_method *methods,
    1120             :         size_t count)
    1121             : {
    1122             :         struct wpabuf *resp;
    1123           4 :         int found = 0;
    1124             :         const struct eap_method *m;
    1125             : 
    1126           4 :         wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");
    1127             : 
    1128             :         /* RFC 3748 - 5.3.2: Expanded Nak */
    1129           4 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
    1130             :                              8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
    1131           4 :         if (resp == NULL)
    1132           0 :                 return NULL;
    1133             : 
    1134           4 :         wpabuf_put_be24(resp, EAP_VENDOR_IETF);
    1135           4 :         wpabuf_put_be32(resp, EAP_TYPE_NAK);
    1136             : 
    1137         100 :         for (m = methods; m; m = m->next) {
    1138         101 :                 if (sm->reqVendor == m->vendor &&
    1139           5 :                     sm->reqVendorMethod == m->method)
    1140           4 :                         continue; /* do not allow the current method again */
    1141          92 :                 if (eap_allowed_method(sm, m->vendor, m->method)) {
    1142           1 :                         wpa_printf(MSG_DEBUG, "EAP: allowed type: "
    1143             :                                    "vendor=%u method=%u",
    1144           1 :                                    m->vendor, m->method);
    1145           1 :                         wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
    1146           1 :                         wpabuf_put_be24(resp, m->vendor);
    1147           1 :                         wpabuf_put_be32(resp, m->method);
    1148             : 
    1149           1 :                         found++;
    1150             :                 }
    1151             :         }
    1152           4 :         if (!found) {
    1153           3 :                 wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");
    1154           3 :                 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
    1155           3 :                 wpabuf_put_be24(resp, EAP_VENDOR_IETF);
    1156           3 :                 wpabuf_put_be32(resp, EAP_TYPE_NONE);
    1157             :         }
    1158             : 
    1159           4 :         eap_update_len(resp);
    1160             : 
    1161           4 :         return resp;
    1162             : }
    1163             : 
    1164             : 
    1165         144 : static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
    1166             : {
    1167             :         struct wpabuf *resp;
    1168             :         u8 *start;
    1169         144 :         int found = 0, expanded_found = 0;
    1170             :         size_t count;
    1171             :         const struct eap_method *methods, *m;
    1172             : 
    1173         288 :         wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "
    1174         144 :                    "vendor=%u method=%u not allowed)", sm->reqMethod,
    1175             :                    sm->reqVendor, sm->reqVendorMethod);
    1176         144 :         methods = eap_peer_get_methods(&count);
    1177         144 :         if (methods == NULL)
    1178           0 :                 return NULL;
    1179         144 :         if (sm->reqMethod == EAP_TYPE_EXPANDED)
    1180           4 :                 return eap_sm_build_expanded_nak(sm, id, methods, count);
    1181             : 
    1182             :         /* RFC 3748 - 5.3.1: Legacy Nak */
    1183         140 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
    1184             :                              sizeof(struct eap_hdr) + 1 + count + 1,
    1185             :                              EAP_CODE_RESPONSE, id);
    1186         140 :         if (resp == NULL)
    1187           0 :                 return NULL;
    1188             : 
    1189         140 :         start = wpabuf_put(resp, 0);
    1190        3500 :         for (m = methods; m; m = m->next) {
    1191        3360 :                 if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)
    1192         140 :                         continue; /* do not allow the current method again */
    1193        3220 :                 if (eap_allowed_method(sm, m->vendor, m->method)) {
    1194         117 :                         if (m->vendor != EAP_VENDOR_IETF) {
    1195           0 :                                 if (expanded_found)
    1196           0 :                                         continue;
    1197           0 :                                 expanded_found = 1;
    1198           0 :                                 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
    1199             :                         } else
    1200         117 :                                 wpabuf_put_u8(resp, m->method);
    1201         117 :                         found++;
    1202             :                 }
    1203             :         }
    1204         140 :         if (!found)
    1205          23 :                 wpabuf_put_u8(resp, EAP_TYPE_NONE);
    1206         140 :         wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found);
    1207             : 
    1208         140 :         eap_update_len(resp);
    1209             : 
    1210         140 :         return resp;
    1211             : }
    1212             : 
    1213             : 
    1214        1668 : static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
    1215             : {
    1216             :         const u8 *pos;
    1217             :         size_t msg_len;
    1218             : 
    1219        1668 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
    1220             :                 "EAP authentication started");
    1221        1668 :         eap_notify_status(sm, "started", "");
    1222             : 
    1223        1668 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req,
    1224             :                                &msg_len);
    1225        1668 :         if (pos == NULL)
    1226        1668 :                 return;
    1227             : 
    1228             :         /*
    1229             :          * RFC 3748 - 5.1: Identity
    1230             :          * Data field may contain a displayable message in UTF-8. If this
    1231             :          * includes NUL-character, only the data before that should be
    1232             :          * displayed. Some EAP implementasitons may piggy-back additional
    1233             :          * options after the NUL.
    1234             :          */
    1235             :         /* TODO: could save displayable message so that it can be shown to the
    1236             :          * user in case of interaction is required */
    1237        1668 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
    1238             :                           pos, msg_len);
    1239             : }
    1240             : 
    1241             : 
    1242             : #ifdef PCSC_FUNCS
    1243             : 
    1244             : /*
    1245             :  * Rules for figuring out MNC length based on IMSI for SIM cards that do not
    1246             :  * include MNC length field.
    1247             :  */
    1248             : static int mnc_len_from_imsi(const char *imsi)
    1249             : {
    1250             :         char mcc_str[4];
    1251             :         unsigned int mcc;
    1252             : 
    1253             :         os_memcpy(mcc_str, imsi, 3);
    1254             :         mcc_str[3] = '\0';
    1255             :         mcc = atoi(mcc_str);
    1256             : 
    1257             :         if (mcc == 228)
    1258             :                 return 2; /* Networks in Switzerland use 2-digit MNC */
    1259             :         if (mcc == 244)
    1260             :                 return 2; /* Networks in Finland use 2-digit MNC */
    1261             : 
    1262             :         return -1;
    1263             : }
    1264             : 
    1265             : 
    1266             : static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
    1267             :                                     size_t max_len, size_t *imsi_len)
    1268             : {
    1269             :         int mnc_len;
    1270             :         char *pos, mnc[4];
    1271             : 
    1272             :         if (*imsi_len + 36 > max_len) {
    1273             :                 wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
    1274             :                 return -1;
    1275             :         }
    1276             : 
    1277             :         /* MNC (2 or 3 digits) */
    1278             :         mnc_len = scard_get_mnc_len(sm->scard_ctx);
    1279             :         if (mnc_len < 0)
    1280             :                 mnc_len = mnc_len_from_imsi(imsi);
    1281             :         if (mnc_len < 0) {
    1282             :                 wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
    1283             :                            "assuming 3");
    1284             :                 mnc_len = 3;
    1285             :         }
    1286             : 
    1287             :         if (mnc_len == 2) {
    1288             :                 mnc[0] = '0';
    1289             :                 mnc[1] = imsi[3];
    1290             :                 mnc[2] = imsi[4];
    1291             :         } else if (mnc_len == 3) {
    1292             :                 mnc[0] = imsi[3];
    1293             :                 mnc[1] = imsi[4];
    1294             :                 mnc[2] = imsi[5];
    1295             :         }
    1296             :         mnc[3] = '\0';
    1297             : 
    1298             :         pos = imsi + *imsi_len;
    1299             :         pos += os_snprintf(pos, imsi + max_len - pos,
    1300             :                            "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
    1301             :                            mnc, imsi[0], imsi[1], imsi[2]);
    1302             :         *imsi_len = pos - imsi;
    1303             : 
    1304             :         return 0;
    1305             : }
    1306             : 
    1307             : 
    1308             : static int eap_sm_imsi_identity(struct eap_sm *sm,
    1309             :                                 struct eap_peer_config *conf)
    1310             : {
    1311             :         enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
    1312             :         char imsi[100];
    1313             :         size_t imsi_len;
    1314             :         struct eap_method_type *m = conf->eap_methods;
    1315             :         int i;
    1316             : 
    1317             :         imsi_len = sizeof(imsi);
    1318             :         if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
    1319             :                 wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
    1320             :                 return -1;
    1321             :         }
    1322             : 
    1323             :         wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
    1324             : 
    1325             :         if (imsi_len < 7) {
    1326             :                 wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity");
    1327             :                 return -1;
    1328             :         }
    1329             : 
    1330             :         if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
    1331             :                 wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
    1332             :                 return -1;
    1333             :         }
    1334             :         wpa_hexdump_ascii(MSG_DEBUG, "IMSI + realm", (u8 *) imsi, imsi_len);
    1335             : 
    1336             :         for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
    1337             :                           m[i].method != EAP_TYPE_NONE); i++) {
    1338             :                 if (m[i].vendor == EAP_VENDOR_IETF &&
    1339             :                     m[i].method == EAP_TYPE_AKA_PRIME) {
    1340             :                         method = EAP_SM_AKA_PRIME;
    1341             :                         break;
    1342             :                 }
    1343             : 
    1344             :                 if (m[i].vendor == EAP_VENDOR_IETF &&
    1345             :                     m[i].method == EAP_TYPE_AKA) {
    1346             :                         method = EAP_SM_AKA;
    1347             :                         break;
    1348             :                 }
    1349             :         }
    1350             : 
    1351             :         os_free(conf->identity);
    1352             :         conf->identity = os_malloc(1 + imsi_len);
    1353             :         if (conf->identity == NULL) {
    1354             :                 wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
    1355             :                            "IMSI-based identity");
    1356             :                 return -1;
    1357             :         }
    1358             : 
    1359             :         switch (method) {
    1360             :         case EAP_SM_SIM:
    1361             :                 conf->identity[0] = '1';
    1362             :                 break;
    1363             :         case EAP_SM_AKA:
    1364             :                 conf->identity[0] = '0';
    1365             :                 break;
    1366             :         case EAP_SM_AKA_PRIME:
    1367             :                 conf->identity[0] = '6';
    1368             :                 break;
    1369             :         }
    1370             :         os_memcpy(conf->identity + 1, imsi, imsi_len);
    1371             :         conf->identity_len = 1 + imsi_len;
    1372             : 
    1373             :         return 0;
    1374             : }
    1375             : 
    1376             : #endif /* PCSC_FUNCS */
    1377             : 
    1378             : 
    1379           0 : static int eap_sm_set_scard_pin(struct eap_sm *sm,
    1380             :                                 struct eap_peer_config *conf)
    1381             : {
    1382             : #ifdef PCSC_FUNCS
    1383             :         if (scard_set_pin(sm->scard_ctx, conf->pin)) {
    1384             :                 /*
    1385             :                  * Make sure the same PIN is not tried again in order to avoid
    1386             :                  * blocking SIM.
    1387             :                  */
    1388             :                 os_free(conf->pin);
    1389             :                 conf->pin = NULL;
    1390             : 
    1391             :                 wpa_printf(MSG_WARNING, "PIN validation failed");
    1392             :                 eap_sm_request_pin(sm);
    1393             :                 return -1;
    1394             :         }
    1395             :         return 0;
    1396             : #else /* PCSC_FUNCS */
    1397           0 :         return -1;
    1398             : #endif /* PCSC_FUNCS */
    1399             : }
    1400             : 
    1401           0 : static int eap_sm_get_scard_identity(struct eap_sm *sm,
    1402             :                                      struct eap_peer_config *conf)
    1403             : {
    1404             : #ifdef PCSC_FUNCS
    1405             :         if (eap_sm_set_scard_pin(sm, conf))
    1406             :                 return -1;
    1407             : 
    1408             :         return eap_sm_imsi_identity(sm, conf);
    1409             : #else /* PCSC_FUNCS */
    1410           0 :         return -1;
    1411             : #endif /* PCSC_FUNCS */
    1412             : }
    1413             : 
    1414             : 
    1415             : /**
    1416             :  * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
    1417             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1418             :  * @id: EAP identifier for the packet
    1419             :  * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
    1420             :  * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
    1421             :  * failure
    1422             :  *
    1423             :  * This function allocates and builds an EAP-Identity/Response packet for the
    1424             :  * current network. The caller is responsible for freeing the returned data.
    1425             :  */
    1426        1752 : struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
    1427             : {
    1428        1752 :         struct eap_peer_config *config = eap_get_config(sm);
    1429             :         struct wpabuf *resp;
    1430             :         const u8 *identity;
    1431             :         size_t identity_len;
    1432             : 
    1433        1752 :         if (config == NULL) {
    1434           0 :                 wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "
    1435             :                            "was not available");
    1436           0 :                 return NULL;
    1437             :         }
    1438             : 
    1439        1779 :         if (sm->m && sm->m->get_identity &&
    1440          27 :             (identity = sm->m->get_identity(sm, sm->eap_method_priv,
    1441             :                                             &identity_len)) != NULL) {
    1442          27 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
    1443             :                                   "identity", identity, identity_len);
    1444        1725 :         } else if (!encrypted && config->anonymous_identity) {
    1445         234 :                 identity = config->anonymous_identity;
    1446         234 :                 identity_len = config->anonymous_identity_len;
    1447         234 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
    1448             :                                   identity, identity_len);
    1449             :         } else {
    1450        1491 :                 identity = config->identity;
    1451        1491 :                 identity_len = config->identity_len;
    1452        1491 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
    1453             :                                   identity, identity_len);
    1454             :         }
    1455             : 
    1456        1752 :         if (identity == NULL) {
    1457           0 :                 wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
    1458             :                            "configuration was not available");
    1459           0 :                 if (config->pcsc) {
    1460           0 :                         if (eap_sm_get_scard_identity(sm, config) < 0)
    1461           0 :                                 return NULL;
    1462           0 :                         identity = config->identity;
    1463           0 :                         identity_len = config->identity_len;
    1464           0 :                         wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
    1465             :                                           "IMSI", identity, identity_len);
    1466             :                 } else {
    1467           0 :                         eap_sm_request_identity(sm);
    1468           0 :                         return NULL;
    1469             :                 }
    1470        1752 :         } else if (config->pcsc) {
    1471           0 :                 if (eap_sm_set_scard_pin(sm, config) < 0)
    1472           0 :                         return NULL;
    1473             :         }
    1474             : 
    1475        1752 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
    1476             :                              EAP_CODE_RESPONSE, id);
    1477        1752 :         if (resp == NULL)
    1478           0 :                 return NULL;
    1479             : 
    1480        1752 :         wpabuf_put_data(resp, identity, identity_len);
    1481             : 
    1482        1752 :         return resp;
    1483             : }
    1484             : 
    1485             : 
    1486           6 : static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
    1487             : {
    1488             :         const u8 *pos;
    1489             :         char *msg;
    1490             :         size_t i, msg_len;
    1491             : 
    1492           6 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req,
    1493             :                                &msg_len);
    1494           6 :         if (pos == NULL)
    1495           0 :                 return;
    1496           6 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
    1497             :                           pos, msg_len);
    1498             : 
    1499           6 :         msg = os_malloc(msg_len + 1);
    1500           6 :         if (msg == NULL)
    1501           0 :                 return;
    1502          12 :         for (i = 0; i < msg_len; i++)
    1503           6 :                 msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
    1504           6 :         msg[msg_len] = '\0';
    1505           6 :         wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
    1506             :                 WPA_EVENT_EAP_NOTIFICATION, msg);
    1507           6 :         os_free(msg);
    1508             : }
    1509             : 
    1510             : 
    1511           6 : static struct wpabuf * eap_sm_buildNotify(int id)
    1512             : {
    1513             :         struct wpabuf *resp;
    1514             : 
    1515           6 :         wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
    1516           6 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
    1517             :                              EAP_CODE_RESPONSE, id);
    1518           6 :         if (resp == NULL)
    1519           0 :                 return NULL;
    1520             : 
    1521           6 :         return resp;
    1522             : }
    1523             : 
    1524             : 
    1525          41 : static void eap_peer_initiate(struct eap_sm *sm, const struct eap_hdr *hdr,
    1526             :                               size_t len)
    1527             : {
    1528             : #ifdef CONFIG_ERP
    1529          41 :         const u8 *pos = (const u8 *) (hdr + 1);
    1530          41 :         const u8 *end = ((const u8 *) hdr) + len;
    1531             :         struct erp_tlvs parse;
    1532             : 
    1533          41 :         if (len < sizeof(*hdr) + 1) {
    1534           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored too short EAP-Initiate");
    1535           0 :                 return;
    1536             :         }
    1537             : 
    1538          41 :         if (*pos != EAP_ERP_TYPE_REAUTH_START) {
    1539           0 :                 wpa_printf(MSG_DEBUG,
    1540             :                            "EAP: Ignored unexpected EAP-Initiate Type=%u",
    1541           0 :                            *pos);
    1542           0 :                 return;
    1543             :         }
    1544             : 
    1545          41 :         pos++;
    1546          41 :         if (pos >= end) {
    1547           0 :                 wpa_printf(MSG_DEBUG,
    1548             :                            "EAP: Too short EAP-Initiate/Re-auth-Start");
    1549           0 :                 return;
    1550             :         }
    1551          41 :         pos++; /* Reserved */
    1552          41 :         wpa_hexdump(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth-Start TVs/TLVs",
    1553          41 :                     pos, end - pos);
    1554             : 
    1555          41 :         if (erp_parse_tlvs(pos, end, &parse, 0) < 0)
    1556           0 :                 goto invalid;
    1557             : 
    1558          41 :         if (parse.domain) {
    1559          82 :                 wpa_hexdump_ascii(MSG_DEBUG,
    1560             :                                   "EAP: EAP-Initiate/Re-auth-Start - Domain name",
    1561          82 :                                   parse.domain, parse.domain_len);
    1562             :                 /* TODO: Derivation of domain specific keys for local ER */
    1563             :         }
    1564             : 
    1565          41 :         if (eap_peer_erp_reauth_start(sm, hdr, len) == 0)
    1566          21 :                 return;
    1567             : 
    1568             : invalid:
    1569             : #endif /* CONFIG_ERP */
    1570          20 :         wpa_printf(MSG_DEBUG,
    1571             :                    "EAP: EAP-Initiate/Re-auth-Start - No suitable ERP keys available - try to start full EAP authentication");
    1572          20 :         eapol_set_bool(sm, EAPOL_eapTriggerStart, TRUE);
    1573             : }
    1574             : 
    1575             : 
    1576          21 : static void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr,
    1577             :                             size_t len)
    1578             : {
    1579             : #ifdef CONFIG_ERP
    1580          21 :         const u8 *pos = (const u8 *) (hdr + 1);
    1581          21 :         const u8 *end = ((const u8 *) hdr) + len;
    1582             :         const u8 *start;
    1583             :         struct erp_tlvs parse;
    1584             :         u8 flags;
    1585             :         u16 seq;
    1586             :         u8 hash[SHA256_MAC_LEN];
    1587             :         size_t hash_len;
    1588             :         struct eap_erp_key *erp;
    1589             :         int max_len;
    1590             :         char nai[254];
    1591             :         u8 seed[4];
    1592          21 :         int auth_tag_ok = 0;
    1593             : 
    1594          21 :         if (len < sizeof(*hdr) + 1) {
    1595           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored too short EAP-Finish");
    1596           0 :                 return;
    1597             :         }
    1598             : 
    1599          21 :         if (*pos != EAP_ERP_TYPE_REAUTH) {
    1600           0 :                 wpa_printf(MSG_DEBUG,
    1601           0 :                            "EAP: Ignored unexpected EAP-Finish Type=%u", *pos);
    1602           0 :                 return;
    1603             :         }
    1604             : 
    1605          21 :         if (len < sizeof(*hdr) + 4) {
    1606           0 :                 wpa_printf(MSG_DEBUG,
    1607             :                            "EAP: Ignored too short EAP-Finish/Re-auth");
    1608           0 :                 return;
    1609             :         }
    1610             : 
    1611          21 :         pos++;
    1612          21 :         flags = *pos++;
    1613          21 :         seq = WPA_GET_BE16(pos);
    1614          21 :         pos += 2;
    1615          21 :         wpa_printf(MSG_DEBUG, "EAP: Flags=0x%x SEQ=%u", flags, seq);
    1616             : 
    1617          21 :         if (seq != sm->erp_seq) {
    1618           0 :                 wpa_printf(MSG_DEBUG,
    1619             :                            "EAP: Unexpected EAP-Finish/Re-auth SEQ=%u", seq);
    1620           0 :                 return;
    1621             :         }
    1622             : 
    1623             :         /*
    1624             :          * Parse TVs/TLVs. Since we do not yet know the length of the
    1625             :          * Authentication Tag, stop parsing if an unknown TV/TLV is seen and
    1626             :          * just try to find the keyName-NAI first so that we can check the
    1627             :          * Authentication Tag.
    1628             :          */
    1629          21 :         if (erp_parse_tlvs(pos, end, &parse, 1) < 0)
    1630           0 :                 return;
    1631             : 
    1632          21 :         if (!parse.keyname) {
    1633           0 :                 wpa_printf(MSG_DEBUG,
    1634             :                            "EAP: No keyName-NAI in EAP-Finish/Re-auth Packet");
    1635           0 :                 return;
    1636             :         }
    1637             : 
    1638          42 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Finish/Re-auth - keyName-NAI",
    1639          42 :                           parse.keyname, parse.keyname_len);
    1640          21 :         if (parse.keyname_len > 253) {
    1641           0 :                 wpa_printf(MSG_DEBUG,
    1642             :                            "EAP: Too long keyName-NAI in EAP-Finish/Re-auth");
    1643           0 :                 return;
    1644             :         }
    1645          21 :         os_memcpy(nai, parse.keyname, parse.keyname_len);
    1646          21 :         nai[parse.keyname_len] = '\0';
    1647             : 
    1648          21 :         erp = eap_erp_get_key_nai(sm, nai);
    1649          21 :         if (!erp) {
    1650           0 :                 wpa_printf(MSG_DEBUG, "EAP: No matching ERP key found for %s",
    1651             :                            nai);
    1652           0 :                 return;
    1653             :         }
    1654             : 
    1655             :         /* Is there enough room for Cryptosuite and Authentication Tag? */
    1656          21 :         start = parse.keyname + parse.keyname_len;
    1657          21 :         max_len = end - start;
    1658          21 :         hash_len = 16;
    1659          21 :         if (max_len < 1 + (int) hash_len) {
    1660           1 :                 wpa_printf(MSG_DEBUG,
    1661             :                            "EAP: Not enough room for Authentication Tag");
    1662           1 :                 if (flags & 0x80)
    1663           1 :                         goto no_auth_tag;
    1664           0 :                 return;
    1665             :         }
    1666          20 :         if (end[-17] != EAP_ERP_CS_HMAC_SHA256_128) {
    1667           0 :                 wpa_printf(MSG_DEBUG, "EAP: Different Cryptosuite used");
    1668           0 :                 if (flags & 0x80)
    1669           0 :                         goto no_auth_tag;
    1670           0 :                 return;
    1671             :         }
    1672             : 
    1673          20 :         if (hmac_sha256(erp->rIK, erp->rIK_len, (const u8 *) hdr,
    1674          20 :                         end - ((const u8 *) hdr) - hash_len, hash) < 0)
    1675           0 :                 return;
    1676          20 :         if (os_memcmp(end - hash_len, hash, hash_len) != 0) {
    1677           0 :                 wpa_printf(MSG_DEBUG,
    1678             :                            "EAP: Authentication Tag mismatch");
    1679           0 :                 return;
    1680             :         }
    1681          20 :         auth_tag_ok = 1;
    1682          20 :         end -= 1 + hash_len;
    1683             : 
    1684             : no_auth_tag:
    1685             :         /*
    1686             :          * Parse TVs/TLVs again now that we know the exact part of the buffer
    1687             :          * that contains them.
    1688             :          */
    1689          21 :         wpa_hexdump(MSG_DEBUG, "EAP: EAP-Finish/Re-Auth TVs/TLVs",
    1690          21 :                     pos, end - pos);
    1691          21 :         if (erp_parse_tlvs(pos, end, &parse, 0) < 0)
    1692           0 :                 return;
    1693             : 
    1694          21 :         if (flags & 0x80 || !auth_tag_ok) {
    1695           1 :                 wpa_printf(MSG_DEBUG,
    1696             :                            "EAP: EAP-Finish/Re-auth indicated failure");
    1697           1 :                 eapol_set_bool(sm, EAPOL_eapFail, TRUE);
    1698           1 :                 eapol_set_bool(sm, EAPOL_eapReq, FALSE);
    1699           1 :                 eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
    1700           1 :                 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
    1701             :                         "EAP authentication failed");
    1702           1 :                 sm->prev_failure = 1;
    1703           1 :                 wpa_printf(MSG_DEBUG,
    1704             :                            "EAP: Drop ERP key to try full authentication on next attempt");
    1705           1 :                 eap_peer_erp_free_key(erp);
    1706           1 :                 return;
    1707             :         }
    1708             : 
    1709          20 :         eap_sm_free_key(sm);
    1710          20 :         sm->eapKeyDataLen = 0;
    1711          20 :         sm->eapKeyData = os_malloc(erp->rRK_len);
    1712          20 :         if (!sm->eapKeyData)
    1713           0 :                 return;
    1714          20 :         sm->eapKeyDataLen = erp->rRK_len;
    1715             : 
    1716          20 :         WPA_PUT_BE16(seed, seq);
    1717          20 :         WPA_PUT_BE16(&seed[2], erp->rRK_len);
    1718          20 :         if (hmac_sha256_kdf(erp->rRK, erp->rRK_len,
    1719             :                             "Re-authentication Master Session Key@ietf.org",
    1720             :                             seed, sizeof(seed),
    1721             :                             sm->eapKeyData, erp->rRK_len) < 0) {
    1722           0 :                 wpa_printf(MSG_DEBUG, "EAP: Could not derive rMSK for ERP");
    1723           0 :                 eap_sm_free_key(sm);
    1724           0 :                 return;
    1725             :         }
    1726          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK",
    1727          20 :                         sm->eapKeyData, sm->eapKeyDataLen);
    1728          20 :         sm->eapKeyAvailable = TRUE;
    1729          20 :         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
    1730          20 :         eapol_set_bool(sm, EAPOL_eapReq, FALSE);
    1731          20 :         eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
    1732          20 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
    1733             :                 "EAP re-authentication completed successfully");
    1734             : #endif /* CONFIG_ERP */
    1735             : }
    1736             : 
    1737             : 
    1738        8323 : static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
    1739             : {
    1740             :         const struct eap_hdr *hdr;
    1741             :         size_t plen;
    1742             :         const u8 *pos;
    1743             : 
    1744        8323 :         sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
    1745        8323 :         sm->reqId = 0;
    1746        8323 :         sm->reqMethod = EAP_TYPE_NONE;
    1747        8323 :         sm->reqVendor = EAP_VENDOR_IETF;
    1748        8323 :         sm->reqVendorMethod = EAP_TYPE_NONE;
    1749             : 
    1750        8323 :         if (req == NULL || wpabuf_len(req) < sizeof(*hdr))
    1751           0 :                 return;
    1752             : 
    1753        8323 :         hdr = wpabuf_head(req);
    1754        8323 :         plen = be_to_host16(hdr->length);
    1755        8323 :         if (plen > wpabuf_len(req)) {
    1756           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
    1757             :                            "(len=%lu plen=%lu)",
    1758             :                            (unsigned long) wpabuf_len(req),
    1759             :                            (unsigned long) plen);
    1760           0 :                 return;
    1761             :         }
    1762             : 
    1763        8323 :         sm->reqId = hdr->identifier;
    1764             : 
    1765        8323 :         if (sm->workaround) {
    1766             :                 const u8 *addr[1];
    1767        8292 :                 addr[0] = wpabuf_head(req);
    1768        8292 :                 sha1_vector(1, addr, &plen, sm->req_sha1);
    1769             :         }
    1770             : 
    1771        8323 :         switch (hdr->code) {
    1772             :         case EAP_CODE_REQUEST:
    1773        6916 :                 if (plen < sizeof(*hdr) + 1) {
    1774           0 :                         wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - "
    1775             :                                    "no Type field");
    1776           0 :                         return;
    1777             :                 }
    1778        6916 :                 sm->rxReq = TRUE;
    1779        6916 :                 pos = (const u8 *) (hdr + 1);
    1780        6916 :                 sm->reqMethod = *pos++;
    1781        6916 :                 if (sm->reqMethod == EAP_TYPE_EXPANDED) {
    1782        1849 :                         if (plen < sizeof(*hdr) + 8) {
    1783           0 :                                 wpa_printf(MSG_DEBUG, "EAP: Ignored truncated "
    1784             :                                            "expanded EAP-Packet (plen=%lu)",
    1785             :                                            (unsigned long) plen);
    1786           0 :                                 return;
    1787             :                         }
    1788        1849 :                         sm->reqVendor = WPA_GET_BE24(pos);
    1789        1849 :                         pos += 3;
    1790        1849 :                         sm->reqVendorMethod = WPA_GET_BE32(pos);
    1791             :                 }
    1792       13832 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d "
    1793             :                            "method=%u vendor=%u vendorMethod=%u",
    1794        6916 :                            sm->reqId, sm->reqMethod, sm->reqVendor,
    1795             :                            sm->reqVendorMethod);
    1796        6916 :                 break;
    1797             :         case EAP_CODE_RESPONSE:
    1798           6 :                 if (sm->selectedMethod == EAP_TYPE_LEAP) {
    1799             :                         /*
    1800             :                          * LEAP differs from RFC 4137 by using reversed roles
    1801             :                          * for mutual authentication and because of this, we
    1802             :                          * need to accept EAP-Response frames if LEAP is used.
    1803             :                          */
    1804           6 :                         if (plen < sizeof(*hdr) + 1) {
    1805           0 :                                 wpa_printf(MSG_DEBUG, "EAP: Too short "
    1806             :                                            "EAP-Response - no Type field");
    1807           0 :                                 return;
    1808             :                         }
    1809           6 :                         sm->rxResp = TRUE;
    1810           6 :                         pos = (const u8 *) (hdr + 1);
    1811           6 :                         sm->reqMethod = *pos;
    1812          12 :                         wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for "
    1813             :                                    "LEAP method=%d id=%d",
    1814           6 :                                    sm->reqMethod, sm->reqId);
    1815           6 :                         break;
    1816             :                 }
    1817           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response");
    1818           0 :                 break;
    1819             :         case EAP_CODE_SUCCESS:
    1820         734 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
    1821         734 :                 eap_notify_status(sm, "completion", "success");
    1822         734 :                 sm->rxSuccess = TRUE;
    1823         734 :                 break;
    1824             :         case EAP_CODE_FAILURE:
    1825         605 :                 wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
    1826         605 :                 eap_notify_status(sm, "completion", "failure");
    1827         605 :                 sm->rxFailure = TRUE;
    1828         605 :                 break;
    1829             :         case EAP_CODE_INITIATE:
    1830          41 :                 eap_peer_initiate(sm, hdr, plen);
    1831          41 :                 break;
    1832             :         case EAP_CODE_FINISH:
    1833          21 :                 eap_peer_finish(sm, hdr, plen);
    1834          21 :                 break;
    1835             :         default:
    1836           0 :                 wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown "
    1837           0 :                            "code %d", hdr->code);
    1838           0 :                 break;
    1839             :         }
    1840             : }
    1841             : 
    1842             : 
    1843        1212 : static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
    1844             :                                   union tls_event_data *data)
    1845             : {
    1846        1212 :         struct eap_sm *sm = ctx;
    1847        1212 :         char *hash_hex = NULL;
    1848             : 
    1849        1212 :         switch (ev) {
    1850             :         case TLS_CERT_CHAIN_SUCCESS:
    1851         581 :                 eap_notify_status(sm, "remote certificate verification",
    1852             :                                   "success");
    1853         581 :                 break;
    1854             :         case TLS_CERT_CHAIN_FAILURE:
    1855          44 :                 wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
    1856             :                         "reason=%d depth=%d subject='%s' err='%s'",
    1857          22 :                         data->cert_fail.reason,
    1858             :                         data->cert_fail.depth,
    1859             :                         data->cert_fail.subject,
    1860             :                         data->cert_fail.reason_txt);
    1861          22 :                 eap_notify_status(sm, "remote certificate verification",
    1862             :                                   data->cert_fail.reason_txt);
    1863          22 :                 break;
    1864             :         case TLS_PEER_CERTIFICATE:
    1865         582 :                 if (!sm->eapol_cb->notify_cert)
    1866           0 :                         break;
    1867             : 
    1868         582 :                 if (data->peer_cert.hash) {
    1869         582 :                         size_t len = data->peer_cert.hash_len * 2 + 1;
    1870         582 :                         hash_hex = os_malloc(len);
    1871         582 :                         if (hash_hex) {
    1872         582 :                                 wpa_snprintf_hex(hash_hex, len,
    1873             :                                                  data->peer_cert.hash,
    1874             :                                                  data->peer_cert.hash_len);
    1875             :                         }
    1876             :                 }
    1877             : 
    1878        1164 :                 sm->eapol_cb->notify_cert(sm->eapol_ctx,
    1879             :                                           data->peer_cert.depth,
    1880             :                                           data->peer_cert.subject,
    1881         582 :                                           data->peer_cert.altsubject,
    1882             :                                           data->peer_cert.num_altsubject,
    1883             :                                           hash_hex, data->peer_cert.cert);
    1884         582 :                 break;
    1885             :         case TLS_ALERT:
    1886          27 :                 if (data->alert.is_local)
    1887          27 :                         eap_notify_status(sm, "local TLS alert",
    1888             :                                           data->alert.description);
    1889             :                 else
    1890           0 :                         eap_notify_status(sm, "remote TLS alert",
    1891             :                                           data->alert.description);
    1892          27 :                 break;
    1893             :         }
    1894             : 
    1895        1212 :         os_free(hash_hex);
    1896        1212 : }
    1897             : 
    1898             : 
    1899             : /**
    1900             :  * eap_peer_sm_init - Allocate and initialize EAP peer state machine
    1901             :  * @eapol_ctx: Context data to be used with eapol_cb calls
    1902             :  * @eapol_cb: Pointer to EAPOL callback functions
    1903             :  * @msg_ctx: Context data for wpa_msg() calls
    1904             :  * @conf: EAP configuration
    1905             :  * Returns: Pointer to the allocated EAP state machine or %NULL on failure
    1906             :  *
    1907             :  * This function allocates and initializes an EAP state machine. In addition,
    1908             :  * this initializes TLS library for the new EAP state machine. eapol_cb pointer
    1909             :  * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP
    1910             :  * state machine. Consequently, the caller must make sure that this data
    1911             :  * structure remains alive while the EAP state machine is active.
    1912             :  */
    1913         600 : struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
    1914             :                                  const struct eapol_callbacks *eapol_cb,
    1915             :                                  void *msg_ctx, struct eap_config *conf)
    1916             : {
    1917             :         struct eap_sm *sm;
    1918             :         struct tls_config tlsconf;
    1919             : 
    1920         600 :         sm = os_zalloc(sizeof(*sm));
    1921         600 :         if (sm == NULL)
    1922           2 :                 return NULL;
    1923         598 :         sm->eapol_ctx = eapol_ctx;
    1924         598 :         sm->eapol_cb = eapol_cb;
    1925         598 :         sm->msg_ctx = msg_ctx;
    1926         598 :         sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
    1927         598 :         sm->wps = conf->wps;
    1928         598 :         dl_list_init(&sm->erp_keys);
    1929             : 
    1930         598 :         os_memset(&tlsconf, 0, sizeof(tlsconf));
    1931         598 :         tlsconf.opensc_engine_path = conf->opensc_engine_path;
    1932         598 :         tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
    1933         598 :         tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
    1934         598 :         tlsconf.openssl_ciphers = conf->openssl_ciphers;
    1935             : #ifdef CONFIG_FIPS
    1936             :         tlsconf.fips_mode = 1;
    1937             : #endif /* CONFIG_FIPS */
    1938         598 :         tlsconf.event_cb = eap_peer_sm_tls_event;
    1939         598 :         tlsconf.cb_ctx = sm;
    1940         598 :         tlsconf.cert_in_cb = conf->cert_in_cb;
    1941         598 :         sm->ssl_ctx = tls_init(&tlsconf);
    1942         598 :         if (sm->ssl_ctx == NULL) {
    1943           4 :                 wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
    1944             :                            "context.");
    1945           4 :                 os_free(sm);
    1946           4 :                 return NULL;
    1947             :         }
    1948             : 
    1949         594 :         sm->ssl_ctx2 = tls_init(&tlsconf);
    1950         594 :         if (sm->ssl_ctx2 == NULL) {
    1951           4 :                 wpa_printf(MSG_INFO, "SSL: Failed to initialize TLS "
    1952             :                            "context (2).");
    1953             :                 /* Run without separate TLS context within TLS tunnel */
    1954             :         }
    1955             : 
    1956         594 :         return sm;
    1957             : }
    1958             : 
    1959             : 
    1960             : /**
    1961             :  * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine
    1962             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1963             :  *
    1964             :  * This function deinitializes EAP state machine and frees all allocated
    1965             :  * resources.
    1966             :  */
    1967         594 : void eap_peer_sm_deinit(struct eap_sm *sm)
    1968             : {
    1969         594 :         if (sm == NULL)
    1970         594 :                 return;
    1971         594 :         eap_deinit_prev_method(sm, "EAP deinit");
    1972         594 :         eap_sm_abort(sm);
    1973         594 :         if (sm->ssl_ctx2)
    1974         590 :                 tls_deinit(sm->ssl_ctx2);
    1975         594 :         tls_deinit(sm->ssl_ctx);
    1976         594 :         eap_peer_erp_free_keys(sm);
    1977         594 :         os_free(sm);
    1978             : }
    1979             : 
    1980             : 
    1981             : /**
    1982             :  * eap_peer_sm_step - Step EAP peer state machine
    1983             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    1984             :  * Returns: 1 if EAP state was changed or 0 if not
    1985             :  *
    1986             :  * This function advances EAP state machine to a new state to match with the
    1987             :  * current variables. This should be called whenever variables used by the EAP
    1988             :  * state machine have changed.
    1989             :  */
    1990       99468 : int eap_peer_sm_step(struct eap_sm *sm)
    1991             : {
    1992       99468 :         int res = 0;
    1993             :         do {
    1994      141735 :                 sm->changed = FALSE;
    1995      141735 :                 SM_STEP_RUN(EAP);
    1996      141735 :                 if (sm->changed)
    1997       42267 :                         res = 1;
    1998      141735 :         } while (sm->changed);
    1999       99468 :         return res;
    2000             : }
    2001             : 
    2002             : 
    2003             : /**
    2004             :  * eap_sm_abort - Abort EAP authentication
    2005             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2006             :  *
    2007             :  * Release system resources that have been allocated for the authentication
    2008             :  * session without fully deinitializing the EAP state machine.
    2009             :  */
    2010       43278 : void eap_sm_abort(struct eap_sm *sm)
    2011             : {
    2012       43278 :         wpabuf_free(sm->lastRespData);
    2013       43278 :         sm->lastRespData = NULL;
    2014       43278 :         wpabuf_free(sm->eapRespData);
    2015       43278 :         sm->eapRespData = NULL;
    2016       43278 :         eap_sm_free_key(sm);
    2017       43278 :         os_free(sm->eapSessionId);
    2018       43278 :         sm->eapSessionId = NULL;
    2019             : 
    2020             :         /* This is not clearly specified in the EAP statemachines draft, but
    2021             :          * it seems necessary to make sure that some of the EAPOL variables get
    2022             :          * cleared for the next authentication. */
    2023       43278 :         eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
    2024       43278 : }
    2025             : 
    2026             : 
    2027             : #ifdef CONFIG_CTRL_IFACE
    2028         376 : static const char * eap_sm_state_txt(int state)
    2029             : {
    2030         376 :         switch (state) {
    2031             :         case EAP_INITIALIZE:
    2032           0 :                 return "INITIALIZE";
    2033             :         case EAP_DISABLED:
    2034           0 :                 return "DISABLED";
    2035             :         case EAP_IDLE:
    2036          22 :                 return "IDLE";
    2037             :         case EAP_RECEIVED:
    2038           0 :                 return "RECEIVED";
    2039             :         case EAP_GET_METHOD:
    2040           0 :                 return "GET_METHOD";
    2041             :         case EAP_METHOD:
    2042           0 :                 return "METHOD";
    2043             :         case EAP_SEND_RESPONSE:
    2044           0 :                 return "SEND_RESPONSE";
    2045             :         case EAP_DISCARD:
    2046           0 :                 return "DISCARD";
    2047             :         case EAP_IDENTITY:
    2048           0 :                 return "IDENTITY";
    2049             :         case EAP_NOTIFICATION:
    2050           0 :                 return "NOTIFICATION";
    2051             :         case EAP_RETRANSMIT:
    2052           0 :                 return "RETRANSMIT";
    2053             :         case EAP_SUCCESS:
    2054         354 :                 return "SUCCESS";
    2055             :         case EAP_FAILURE:
    2056           0 :                 return "FAILURE";
    2057             :         default:
    2058           0 :                 return "UNKNOWN";
    2059             :         }
    2060             : }
    2061             : #endif /* CONFIG_CTRL_IFACE */
    2062             : 
    2063             : 
    2064             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
    2065        5079 : static const char * eap_sm_method_state_txt(EapMethodState state)
    2066             : {
    2067        5079 :         switch (state) {
    2068             :         case METHOD_NONE:
    2069           0 :                 return "NONE";
    2070             :         case METHOD_INIT:
    2071          82 :                 return "INIT";
    2072             :         case METHOD_CONT:
    2073          11 :                 return "CONT";
    2074             :         case METHOD_MAY_CONT:
    2075        3860 :                 return "MAY_CONT";
    2076             :         case METHOD_DONE:
    2077        1126 :                 return "DONE";
    2078             :         default:
    2079           0 :                 return "UNKNOWN";
    2080             :         }
    2081             : }
    2082             : 
    2083             : 
    2084        5079 : static const char * eap_sm_decision_txt(EapDecision decision)
    2085             : {
    2086        5079 :         switch (decision) {
    2087             :         case DECISION_FAIL:
    2088        4299 :                 return "FAIL";
    2089             :         case DECISION_COND_SUCC:
    2090         179 :                 return "COND_SUCC";
    2091             :         case DECISION_UNCOND_SUCC:
    2092         601 :                 return "UNCOND_SUCC";
    2093             :         default:
    2094           0 :                 return "UNKNOWN";
    2095             :         }
    2096             : }
    2097             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    2098             : 
    2099             : 
    2100             : #ifdef CONFIG_CTRL_IFACE
    2101             : 
    2102             : /**
    2103             :  * eap_sm_get_status - Get EAP state machine status
    2104             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2105             :  * @buf: Buffer for status information
    2106             :  * @buflen: Maximum buffer length
    2107             :  * @verbose: Whether to include verbose status information
    2108             :  * Returns: Number of bytes written to buf.
    2109             :  *
    2110             :  * Query EAP state machine for status information. This function fills in a
    2111             :  * text area with current status information from the EAPOL state machine. If
    2112             :  * the buffer (buf) is not large enough, status information will be truncated
    2113             :  * to fit the buffer.
    2114             :  */
    2115         376 : int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
    2116             : {
    2117             :         int len, ret;
    2118             : 
    2119         376 :         if (sm == NULL)
    2120           0 :                 return 0;
    2121             : 
    2122         376 :         len = os_snprintf(buf, buflen,
    2123             :                           "EAP state=%s\n",
    2124         376 :                           eap_sm_state_txt(sm->EAP_state));
    2125         376 :         if (os_snprintf_error(buflen, len))
    2126           0 :                 return 0;
    2127             : 
    2128         376 :         if (sm->selectedMethod != EAP_TYPE_NONE) {
    2129             :                 const char *name;
    2130         354 :                 if (sm->m) {
    2131         354 :                         name = sm->m->name;
    2132             :                 } else {
    2133           0 :                         const struct eap_method *m =
    2134           0 :                                 eap_peer_get_eap_method(EAP_VENDOR_IETF,
    2135             :                                                         sm->selectedMethod);
    2136           0 :                         if (m)
    2137           0 :                                 name = m->name;
    2138             :                         else
    2139           0 :                                 name = "?";
    2140             :                 }
    2141         354 :                 ret = os_snprintf(buf + len, buflen - len,
    2142             :                                   "selectedMethod=%d (EAP-%s)\n",
    2143         354 :                                   sm->selectedMethod, name);
    2144         354 :                 if (os_snprintf_error(buflen - len, ret))
    2145           0 :                         return len;
    2146         354 :                 len += ret;
    2147             : 
    2148         354 :                 if (sm->m && sm->m->get_status) {
    2149         198 :                         len += sm->m->get_status(sm, sm->eap_method_priv,
    2150             :                                                  buf + len, buflen - len,
    2151             :                                                  verbose);
    2152             :                 }
    2153             :         }
    2154             : 
    2155         376 :         if (verbose) {
    2156           2 :                 ret = os_snprintf(buf + len, buflen - len,
    2157             :                                   "reqMethod=%d\n"
    2158             :                                   "methodState=%s\n"
    2159             :                                   "decision=%s\n"
    2160             :                                   "ClientTimeout=%d\n",
    2161           1 :                                   sm->reqMethod,
    2162             :                                   eap_sm_method_state_txt(sm->methodState),
    2163             :                                   eap_sm_decision_txt(sm->decision),
    2164             :                                   sm->ClientTimeout);
    2165           1 :                 if (os_snprintf_error(buflen - len, ret))
    2166           0 :                         return len;
    2167           1 :                 len += ret;
    2168             :         }
    2169             : 
    2170         376 :         return len;
    2171             : }
    2172             : #endif /* CONFIG_CTRL_IFACE */
    2173             : 
    2174             : 
    2175             : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
    2176          37 : static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
    2177             :                            const char *msg, size_t msglen)
    2178             : {
    2179             :         struct eap_peer_config *config;
    2180          37 :         const char *txt = NULL;
    2181             :         char *tmp;
    2182             : 
    2183          37 :         if (sm == NULL)
    2184           0 :                 return;
    2185          37 :         config = eap_get_config(sm);
    2186          37 :         if (config == NULL)
    2187           0 :                 return;
    2188             : 
    2189          37 :         switch (field) {
    2190             :         case WPA_CTRL_REQ_EAP_IDENTITY:
    2191           2 :                 config->pending_req_identity++;
    2192           2 :                 break;
    2193             :         case WPA_CTRL_REQ_EAP_PASSWORD:
    2194           7 :                 config->pending_req_password++;
    2195           7 :                 break;
    2196             :         case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
    2197           0 :                 config->pending_req_new_password++;
    2198           0 :                 break;
    2199             :         case WPA_CTRL_REQ_EAP_PIN:
    2200           0 :                 config->pending_req_pin++;
    2201           0 :                 break;
    2202             :         case WPA_CTRL_REQ_EAP_OTP:
    2203           2 :                 if (msg) {
    2204           2 :                         tmp = os_malloc(msglen + 3);
    2205           2 :                         if (tmp == NULL)
    2206           0 :                                 return;
    2207           2 :                         tmp[0] = '[';
    2208           2 :                         os_memcpy(tmp + 1, msg, msglen);
    2209           2 :                         tmp[msglen + 1] = ']';
    2210           2 :                         tmp[msglen + 2] = '\0';
    2211           2 :                         txt = tmp;
    2212           2 :                         os_free(config->pending_req_otp);
    2213           2 :                         config->pending_req_otp = tmp;
    2214           2 :                         config->pending_req_otp_len = msglen + 3;
    2215             :                 } else {
    2216           0 :                         if (config->pending_req_otp == NULL)
    2217           0 :                                 return;
    2218           0 :                         txt = config->pending_req_otp;
    2219             :                 }
    2220           2 :                 break;
    2221             :         case WPA_CTRL_REQ_EAP_PASSPHRASE:
    2222           5 :                 config->pending_req_passphrase++;
    2223           5 :                 break;
    2224             :         case WPA_CTRL_REQ_SIM:
    2225          21 :                 txt = msg;
    2226          21 :                 break;
    2227             :         default:
    2228           0 :                 return;
    2229             :         }
    2230             : 
    2231          37 :         if (sm->eapol_cb->eap_param_needed)
    2232          37 :                 sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
    2233             : }
    2234             : #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    2235             : #define eap_sm_request(sm, type, msg, msglen) do { } while (0)
    2236             : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
    2237             : 
    2238        1332 : const char * eap_sm_get_method_name(struct eap_sm *sm)
    2239             : {
    2240        1332 :         if (sm->m == NULL)
    2241         170 :                 return "UNKNOWN";
    2242        1162 :         return sm->m->name;
    2243             : }
    2244             : 
    2245             : 
    2246             : /**
    2247             :  * eap_sm_request_identity - Request identity from user (ctrl_iface)
    2248             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2249             :  *
    2250             :  * EAP methods can call this function to request identity information for the
    2251             :  * current network. This is normally called when the identity is not included
    2252             :  * in the network configuration. The request will be sent to monitor programs
    2253             :  * through the control interface.
    2254             :  */
    2255           2 : void eap_sm_request_identity(struct eap_sm *sm)
    2256             : {
    2257           2 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
    2258           2 : }
    2259             : 
    2260             : 
    2261             : /**
    2262             :  * eap_sm_request_password - Request password from user (ctrl_iface)
    2263             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2264             :  *
    2265             :  * EAP methods can call this function to request password information for the
    2266             :  * current network. This is normally called when the password is not included
    2267             :  * in the network configuration. The request will be sent to monitor programs
    2268             :  * through the control interface.
    2269             :  */
    2270           7 : void eap_sm_request_password(struct eap_sm *sm)
    2271             : {
    2272           7 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
    2273           7 : }
    2274             : 
    2275             : 
    2276             : /**
    2277             :  * eap_sm_request_new_password - Request new password from user (ctrl_iface)
    2278             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2279             :  *
    2280             :  * EAP methods can call this function to request new password information for
    2281             :  * the current network. This is normally called when the EAP method indicates
    2282             :  * that the current password has expired and password change is required. The
    2283             :  * request will be sent to monitor programs through the control interface.
    2284             :  */
    2285           0 : void eap_sm_request_new_password(struct eap_sm *sm)
    2286             : {
    2287           0 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
    2288           0 : }
    2289             : 
    2290             : 
    2291             : /**
    2292             :  * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
    2293             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2294             :  *
    2295             :  * EAP methods can call this function to request SIM or smart card PIN
    2296             :  * information for the current network. This is normally called when the PIN is
    2297             :  * not included in the network configuration. The request will be sent to
    2298             :  * monitor programs through the control interface.
    2299             :  */
    2300           0 : void eap_sm_request_pin(struct eap_sm *sm)
    2301             : {
    2302           0 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
    2303           0 : }
    2304             : 
    2305             : 
    2306             : /**
    2307             :  * eap_sm_request_otp - Request one time password from user (ctrl_iface)
    2308             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2309             :  * @msg: Message to be displayed to the user when asking for OTP
    2310             :  * @msg_len: Length of the user displayable message
    2311             :  *
    2312             :  * EAP methods can call this function to request open time password (OTP) for
    2313             :  * the current network. The request will be sent to monitor programs through
    2314             :  * the control interface.
    2315             :  */
    2316           2 : void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
    2317             : {
    2318           2 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
    2319           2 : }
    2320             : 
    2321             : 
    2322             : /**
    2323             :  * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
    2324             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2325             :  *
    2326             :  * EAP methods can call this function to request passphrase for a private key
    2327             :  * for the current network. This is normally called when the passphrase is not
    2328             :  * included in the network configuration. The request will be sent to monitor
    2329             :  * programs through the control interface.
    2330             :  */
    2331           5 : void eap_sm_request_passphrase(struct eap_sm *sm)
    2332             : {
    2333           5 :         eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
    2334           5 : }
    2335             : 
    2336             : 
    2337             : /**
    2338             :  * eap_sm_request_sim - Request external SIM processing
    2339             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2340             :  * @req: EAP method specific request
    2341             :  */
    2342          21 : void eap_sm_request_sim(struct eap_sm *sm, const char *req)
    2343             : {
    2344          21 :         eap_sm_request(sm, WPA_CTRL_REQ_SIM, req, os_strlen(req));
    2345          21 : }
    2346             : 
    2347             : 
    2348             : /**
    2349             :  * eap_sm_notify_ctrl_attached - Notification of attached monitor
    2350             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2351             :  *
    2352             :  * Notify EAP state machines that a monitor was attached to the control
    2353             :  * interface to trigger re-sending of pending requests for user input.
    2354             :  */
    2355         888 : void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
    2356             : {
    2357         888 :         struct eap_peer_config *config = eap_get_config(sm);
    2358             : 
    2359         888 :         if (config == NULL)
    2360        1582 :                 return;
    2361             : 
    2362             :         /* Re-send any pending requests for user data since a new control
    2363             :          * interface was added. This handles cases where the EAP authentication
    2364             :          * starts immediately after system startup when the user interface is
    2365             :          * not yet running. */
    2366         194 :         if (config->pending_req_identity)
    2367           0 :                 eap_sm_request_identity(sm);
    2368         194 :         if (config->pending_req_password)
    2369           0 :                 eap_sm_request_password(sm);
    2370         194 :         if (config->pending_req_new_password)
    2371           0 :                 eap_sm_request_new_password(sm);
    2372         194 :         if (config->pending_req_otp)
    2373           0 :                 eap_sm_request_otp(sm, NULL, 0);
    2374         194 :         if (config->pending_req_pin)
    2375           0 :                 eap_sm_request_pin(sm);
    2376         194 :         if (config->pending_req_passphrase)
    2377           0 :                 eap_sm_request_passphrase(sm);
    2378             : }
    2379             : 
    2380             : 
    2381         298 : static int eap_allowed_phase2_type(int vendor, int type)
    2382             : {
    2383         298 :         if (vendor != EAP_VENDOR_IETF)
    2384          36 :                 return 0;
    2385         262 :         return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
    2386             :                 type != EAP_TYPE_FAST;
    2387             : }
    2388             : 
    2389             : 
    2390             : /**
    2391             :  * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
    2392             :  * @name: EAP method name, e.g., MD5
    2393             :  * @vendor: Buffer for returning EAP Vendor-Id
    2394             :  * Returns: EAP method type or %EAP_TYPE_NONE if not found
    2395             :  *
    2396             :  * This function maps EAP type names into EAP type numbers that are allowed for
    2397             :  * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
    2398             :  * EAP-PEAP, EAP-TTLS, and EAP-FAST.
    2399             :  */
    2400          82 : u32 eap_get_phase2_type(const char *name, int *vendor)
    2401             : {
    2402             :         int v;
    2403          82 :         u32 type = eap_peer_get_type(name, &v);
    2404          82 :         if (eap_allowed_phase2_type(v, type)) {
    2405          82 :                 *vendor = v;
    2406          82 :                 return type;
    2407             :         }
    2408           0 :         *vendor = EAP_VENDOR_IETF;
    2409           0 :         return EAP_TYPE_NONE;
    2410             : }
    2411             : 
    2412             : 
    2413             : /**
    2414             :  * eap_get_phase2_types - Get list of allowed EAP phase 2 types
    2415             :  * @config: Pointer to a network configuration
    2416             :  * @count: Pointer to a variable to be filled with number of returned EAP types
    2417             :  * Returns: Pointer to allocated type list or %NULL on failure
    2418             :  *
    2419             :  * This function generates an array of allowed EAP phase 2 (tunneled) types for
    2420             :  * the given network configuration.
    2421             :  */
    2422           9 : struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
    2423             :                                               size_t *count)
    2424             : {
    2425             :         struct eap_method_type *buf;
    2426             :         u32 method;
    2427             :         int vendor;
    2428             :         size_t mcount;
    2429             :         const struct eap_method *methods, *m;
    2430             : 
    2431           9 :         methods = eap_peer_get_methods(&mcount);
    2432           9 :         if (methods == NULL)
    2433           0 :                 return NULL;
    2434           9 :         *count = 0;
    2435           9 :         buf = os_malloc(mcount * sizeof(struct eap_method_type));
    2436           9 :         if (buf == NULL)
    2437           0 :                 return NULL;
    2438             : 
    2439         225 :         for (m = methods; m; m = m->next) {
    2440         216 :                 vendor = m->vendor;
    2441         216 :                 method = m->method;
    2442         216 :                 if (eap_allowed_phase2_type(vendor, method)) {
    2443         153 :                         if (vendor == EAP_VENDOR_IETF &&
    2444          18 :                             method == EAP_TYPE_TLS && config &&
    2445           9 :                             config->private_key2 == NULL)
    2446           9 :                                 continue;
    2447         144 :                         buf[*count].vendor = vendor;
    2448         144 :                         buf[*count].method = method;
    2449         144 :                         (*count)++;
    2450             :                 }
    2451             :         }
    2452             : 
    2453           9 :         return buf;
    2454             : }
    2455             : 
    2456             : 
    2457             : /**
    2458             :  * eap_set_fast_reauth - Update fast_reauth setting
    2459             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2460             :  * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled
    2461             :  */
    2462        3428 : void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
    2463             : {
    2464        3428 :         sm->fast_reauth = enabled;
    2465        3428 : }
    2466             : 
    2467             : 
    2468             : /**
    2469             :  * eap_set_workaround - Update EAP workarounds setting
    2470             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2471             :  * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
    2472             :  */
    2473        3428 : void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
    2474             : {
    2475        3428 :         sm->workaround = workaround;
    2476        3428 : }
    2477             : 
    2478             : 
    2479             : /**
    2480             :  * eap_get_config - Get current network configuration
    2481             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2482             :  * Returns: Pointer to the current network configuration or %NULL if not found
    2483             :  *
    2484             :  * EAP peer methods should avoid using this function if they can use other
    2485             :  * access functions, like eap_get_config_identity() and
    2486             :  * eap_get_config_password(), that do not require direct access to
    2487             :  * struct eap_peer_config.
    2488             :  */
    2489       18241 : struct eap_peer_config * eap_get_config(struct eap_sm *sm)
    2490             : {
    2491       18241 :         return sm->eapol_cb->get_config(sm->eapol_ctx);
    2492             : }
    2493             : 
    2494             : 
    2495             : /**
    2496             :  * eap_get_config_identity - Get identity from the network configuration
    2497             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2498             :  * @len: Buffer for the length of the identity
    2499             :  * Returns: Pointer to the identity or %NULL if not found
    2500             :  */
    2501        2147 : const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
    2502             : {
    2503        2147 :         struct eap_peer_config *config = eap_get_config(sm);
    2504        2147 :         if (config == NULL)
    2505           0 :                 return NULL;
    2506        2147 :         *len = config->identity_len;
    2507        2147 :         return config->identity;
    2508             : }
    2509             : 
    2510             : 
    2511           6 : static int eap_get_ext_password(struct eap_sm *sm,
    2512             :                                 struct eap_peer_config *config)
    2513             : {
    2514             :         char *name;
    2515             : 
    2516           6 :         if (config->password == NULL)
    2517           0 :                 return -1;
    2518             : 
    2519           6 :         name = os_zalloc(config->password_len + 1);
    2520           6 :         if (name == NULL)
    2521           0 :                 return -1;
    2522           6 :         os_memcpy(name, config->password, config->password_len);
    2523             : 
    2524           6 :         ext_password_free(sm->ext_pw_buf);
    2525           6 :         sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
    2526           6 :         os_free(name);
    2527             : 
    2528           6 :         return sm->ext_pw_buf == NULL ? -1 : 0;
    2529             : }
    2530             : 
    2531             : 
    2532             : /**
    2533             :  * eap_get_config_password - Get password from the network configuration
    2534             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2535             :  * @len: Buffer for the length of the password
    2536             :  * Returns: Pointer to the password or %NULL if not found
    2537             :  */
    2538        1078 : const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
    2539             : {
    2540        1078 :         struct eap_peer_config *config = eap_get_config(sm);
    2541        1078 :         if (config == NULL)
    2542           0 :                 return NULL;
    2543             : 
    2544        1078 :         if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
    2545           4 :                 if (eap_get_ext_password(sm, config) < 0)
    2546           0 :                         return NULL;
    2547           4 :                 *len = wpabuf_len(sm->ext_pw_buf);
    2548           4 :                 return wpabuf_head(sm->ext_pw_buf);
    2549             :         }
    2550             : 
    2551        1074 :         *len = config->password_len;
    2552        1074 :         return config->password;
    2553             : }
    2554             : 
    2555             : 
    2556             : /**
    2557             :  * eap_get_config_password2 - Get password from the network configuration
    2558             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2559             :  * @len: Buffer for the length of the password
    2560             :  * @hash: Buffer for returning whether the password is stored as a
    2561             :  * NtPasswordHash instead of plaintext password; can be %NULL if this
    2562             :  * information is not needed
    2563             :  * Returns: Pointer to the password or %NULL if not found
    2564             :  */
    2565         198 : const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
    2566             : {
    2567         198 :         struct eap_peer_config *config = eap_get_config(sm);
    2568         198 :         if (config == NULL)
    2569           0 :                 return NULL;
    2570             : 
    2571         198 :         if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
    2572           2 :                 if (eap_get_ext_password(sm, config) < 0)
    2573           0 :                         return NULL;
    2574           2 :                 if (hash)
    2575           2 :                         *hash = 0;
    2576           2 :                 *len = wpabuf_len(sm->ext_pw_buf);
    2577           2 :                 return wpabuf_head(sm->ext_pw_buf);
    2578             :         }
    2579             : 
    2580         196 :         *len = config->password_len;
    2581         196 :         if (hash)
    2582         196 :                 *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
    2583         196 :         return config->password;
    2584             : }
    2585             : 
    2586             : 
    2587             : /**
    2588             :  * eap_get_config_new_password - Get new password from network configuration
    2589             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2590             :  * @len: Buffer for the length of the new password
    2591             :  * Returns: Pointer to the new password or %NULL if not found
    2592             :  */
    2593           0 : const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
    2594             : {
    2595           0 :         struct eap_peer_config *config = eap_get_config(sm);
    2596           0 :         if (config == NULL)
    2597           0 :                 return NULL;
    2598           0 :         *len = config->new_password_len;
    2599           0 :         return config->new_password;
    2600             : }
    2601             : 
    2602             : 
    2603             : /**
    2604             :  * eap_get_config_otp - Get one-time password from the network configuration
    2605             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2606             :  * @len: Buffer for the length of the one-time password
    2607             :  * Returns: Pointer to the one-time password or %NULL if not found
    2608             :  */
    2609          18 : const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len)
    2610             : {
    2611          18 :         struct eap_peer_config *config = eap_get_config(sm);
    2612          18 :         if (config == NULL)
    2613           0 :                 return NULL;
    2614          18 :         *len = config->otp_len;
    2615          18 :         return config->otp;
    2616             : }
    2617             : 
    2618             : 
    2619             : /**
    2620             :  * eap_clear_config_otp - Clear used one-time password
    2621             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2622             :  *
    2623             :  * This function clears a used one-time password (OTP) from the current network
    2624             :  * configuration. This should be called when the OTP has been used and is not
    2625             :  * needed anymore.
    2626             :  */
    2627           2 : void eap_clear_config_otp(struct eap_sm *sm)
    2628             : {
    2629           2 :         struct eap_peer_config *config = eap_get_config(sm);
    2630           2 :         if (config == NULL)
    2631           2 :                 return;
    2632           2 :         os_memset(config->otp, 0, config->otp_len);
    2633           2 :         os_free(config->otp);
    2634           2 :         config->otp = NULL;
    2635           2 :         config->otp_len = 0;
    2636             : }
    2637             : 
    2638             : 
    2639             : /**
    2640             :  * eap_get_config_phase1 - Get phase1 data from the network configuration
    2641             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2642             :  * Returns: Pointer to the phase1 data or %NULL if not found
    2643             :  */
    2644         896 : const char * eap_get_config_phase1(struct eap_sm *sm)
    2645             : {
    2646         896 :         struct eap_peer_config *config = eap_get_config(sm);
    2647         896 :         if (config == NULL)
    2648           0 :                 return NULL;
    2649         896 :         return config->phase1;
    2650             : }
    2651             : 
    2652             : 
    2653             : /**
    2654             :  * eap_get_config_phase2 - Get phase2 data from the network configuration
    2655             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2656             :  * Returns: Pointer to the phase1 data or %NULL if not found
    2657             :  */
    2658           0 : const char * eap_get_config_phase2(struct eap_sm *sm)
    2659             : {
    2660           0 :         struct eap_peer_config *config = eap_get_config(sm);
    2661           0 :         if (config == NULL)
    2662           0 :                 return NULL;
    2663           0 :         return config->phase2;
    2664             : }
    2665             : 
    2666             : 
    2667         490 : int eap_get_config_fragment_size(struct eap_sm *sm)
    2668             : {
    2669         490 :         struct eap_peer_config *config = eap_get_config(sm);
    2670         490 :         if (config == NULL)
    2671           0 :                 return -1;
    2672         490 :         return config->fragment_size;
    2673             : }
    2674             : 
    2675             : 
    2676             : /**
    2677             :  * eap_key_available - Get key availability (eapKeyAvailable variable)
    2678             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2679             :  * Returns: 1 if EAP keying material is available, 0 if not
    2680             :  */
    2681        6533 : int eap_key_available(struct eap_sm *sm)
    2682             : {
    2683        6533 :         return sm ? sm->eapKeyAvailable : 0;
    2684             : }
    2685             : 
    2686             : 
    2687             : /**
    2688             :  * eap_notify_success - Notify EAP state machine about external success trigger
    2689             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2690             :  *
    2691             :  * This function is called when external event, e.g., successful completion of
    2692             :  * WPA-PSK key handshake, is indicating that EAP state machine should move to
    2693             :  * success state. This is mainly used with security modes that do not use EAP
    2694             :  * state machine (e.g., WPA-PSK).
    2695             :  */
    2696        1284 : void eap_notify_success(struct eap_sm *sm)
    2697             : {
    2698        1284 :         if (sm) {
    2699        1284 :                 sm->decision = DECISION_COND_SUCC;
    2700        1284 :                 sm->EAP_state = EAP_SUCCESS;
    2701             :         }
    2702        1284 : }
    2703             : 
    2704             : 
    2705             : /**
    2706             :  * eap_notify_lower_layer_success - Notification of lower layer success
    2707             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2708             :  *
    2709             :  * Notify EAP state machines that a lower layer has detected a successful
    2710             :  * authentication. This is used to recover from dropped EAP-Success messages.
    2711             :  */
    2712        3222 : void eap_notify_lower_layer_success(struct eap_sm *sm)
    2713             : {
    2714        3222 :         if (sm == NULL)
    2715           0 :                 return;
    2716             : 
    2717        4431 :         if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
    2718        1767 :             sm->decision == DECISION_FAIL ||
    2719        1040 :             (sm->methodState != METHOD_MAY_CONT &&
    2720         482 :              sm->methodState != METHOD_DONE))
    2721        2759 :                 return;
    2722             : 
    2723         463 :         if (sm->eapKeyData != NULL)
    2724           6 :                 sm->eapKeyAvailable = TRUE;
    2725         463 :         eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
    2726         463 :         wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
    2727             :                 "EAP authentication completed successfully (based on lower "
    2728             :                 "layer success)");
    2729             : }
    2730             : 
    2731             : 
    2732             : /**
    2733             :  * eap_get_eapSessionId - Get Session-Id from EAP state machine
    2734             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2735             :  * @len: Pointer to variable that will be set to number of bytes in the session
    2736             :  * Returns: Pointer to the EAP Session-Id or %NULL on failure
    2737             :  *
    2738             :  * Fetch EAP Session-Id from the EAP state machine. The Session-Id is available
    2739             :  * only after a successful authentication. EAP state machine continues to manage
    2740             :  * the Session-Id and the caller must not change or free the returned data.
    2741             :  */
    2742        1065 : const u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len)
    2743             : {
    2744        1065 :         if (sm == NULL || sm->eapSessionId == NULL) {
    2745         724 :                 *len = 0;
    2746         724 :                 return NULL;
    2747             :         }
    2748             : 
    2749         341 :         *len = sm->eapSessionIdLen;
    2750         341 :         return sm->eapSessionId;
    2751             : }
    2752             : 
    2753             : 
    2754             : /**
    2755             :  * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
    2756             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2757             :  * @len: Pointer to variable that will be set to number of bytes in the key
    2758             :  * Returns: Pointer to the EAP keying data or %NULL on failure
    2759             :  *
    2760             :  * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
    2761             :  * key is available only after a successful authentication. EAP state machine
    2762             :  * continues to manage the key data and the caller must not change or free the
    2763             :  * returned data.
    2764             :  */
    2765        1451 : const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
    2766             : {
    2767        1451 :         if (sm == NULL || sm->eapKeyData == NULL) {
    2768           0 :                 *len = 0;
    2769           0 :                 return NULL;
    2770             :         }
    2771             : 
    2772        1451 :         *len = sm->eapKeyDataLen;
    2773        1451 :         return sm->eapKeyData;
    2774             : }
    2775             : 
    2776             : 
    2777             : /**
    2778             :  * eap_get_eapKeyData - Get EAP response data
    2779             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2780             :  * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
    2781             :  *
    2782             :  * Fetch EAP response (eapRespData) from the EAP state machine. This data is
    2783             :  * available when EAP state machine has processed an incoming EAP request. The
    2784             :  * EAP state machine does not maintain a reference to the response after this
    2785             :  * function is called and the caller is responsible for freeing the data.
    2786             :  */
    2787        6720 : struct wpabuf * eap_get_eapRespData(struct eap_sm *sm)
    2788             : {
    2789             :         struct wpabuf *resp;
    2790             : 
    2791        6720 :         if (sm == NULL || sm->eapRespData == NULL)
    2792           0 :                 return NULL;
    2793             : 
    2794        6720 :         resp = sm->eapRespData;
    2795        6720 :         sm->eapRespData = NULL;
    2796             : 
    2797        6720 :         return resp;
    2798             : }
    2799             : 
    2800             : 
    2801             : /**
    2802             :  * eap_sm_register_scard_ctx - Notification of smart card context
    2803             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2804             :  * @ctx: Context data for smart card operations
    2805             :  *
    2806             :  * Notify EAP state machines of context data for smart card operations. This
    2807             :  * context data will be used as a parameter for scard_*() functions.
    2808             :  */
    2809         577 : void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
    2810             : {
    2811         577 :         if (sm)
    2812         577 :                 sm->scard_ctx = ctx;
    2813         577 : }
    2814             : 
    2815             : 
    2816             : /**
    2817             :  * eap_set_config_blob - Set or add a named configuration blob
    2818             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2819             :  * @blob: New value for the blob
    2820             :  *
    2821             :  * Adds a new configuration blob or replaces the current value of an existing
    2822             :  * blob.
    2823             :  */
    2824          10 : void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
    2825             : {
    2826             : #ifndef CONFIG_NO_CONFIG_BLOBS
    2827          10 :         sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
    2828             : #endif /* CONFIG_NO_CONFIG_BLOBS */
    2829          10 : }
    2830             : 
    2831             : 
    2832             : /**
    2833             :  * eap_get_config_blob - Get a named configuration blob
    2834             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2835             :  * @name: Name of the blob
    2836             :  * Returns: Pointer to blob data or %NULL if not found
    2837             :  */
    2838          26 : const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
    2839             :                                                    const char *name)
    2840             : {
    2841             : #ifndef CONFIG_NO_CONFIG_BLOBS
    2842          26 :         return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
    2843             : #else /* CONFIG_NO_CONFIG_BLOBS */
    2844             :         return NULL;
    2845             : #endif /* CONFIG_NO_CONFIG_BLOBS */
    2846             : }
    2847             : 
    2848             : 
    2849             : /**
    2850             :  * eap_set_force_disabled - Set force_disabled flag
    2851             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2852             :  * @disabled: 1 = EAP disabled, 0 = EAP enabled
    2853             :  *
    2854             :  * This function is used to force EAP state machine to be disabled when it is
    2855             :  * not in use (e.g., with WPA-PSK or plaintext connections).
    2856             :  */
    2857        3428 : void eap_set_force_disabled(struct eap_sm *sm, int disabled)
    2858             : {
    2859        3428 :         sm->force_disabled = disabled;
    2860        3428 : }
    2861             : 
    2862             : 
    2863             : /**
    2864             :  * eap_set_external_sim - Set external_sim flag
    2865             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2866             :  * @external_sim: Whether external SIM/USIM processing is used
    2867             :  */
    2868        3428 : void eap_set_external_sim(struct eap_sm *sm, int external_sim)
    2869             : {
    2870        3428 :         sm->external_sim = external_sim;
    2871        3428 : }
    2872             : 
    2873             : 
    2874             :  /**
    2875             :  * eap_notify_pending - Notify that EAP method is ready to re-process a request
    2876             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2877             :  *
    2878             :  * An EAP method can perform a pending operation (e.g., to get a response from
    2879             :  * an external process). Once the response is available, this function can be
    2880             :  * used to request EAPOL state machine to retry delivering the previously
    2881             :  * received (and still unanswered) EAP request to EAP state machine.
    2882             :  */
    2883           1 : void eap_notify_pending(struct eap_sm *sm)
    2884             : {
    2885           1 :         sm->eapol_cb->notify_pending(sm->eapol_ctx);
    2886           1 : }
    2887             : 
    2888             : 
    2889             : /**
    2890             :  * eap_invalidate_cached_session - Mark cached session data invalid
    2891             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2892             :  */
    2893       21064 : void eap_invalidate_cached_session(struct eap_sm *sm)
    2894             : {
    2895       21064 :         if (sm)
    2896       21064 :                 eap_deinit_prev_method(sm, "invalidate");
    2897       21064 : }
    2898             : 
    2899             : 
    2900        5365 : int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf)
    2901             : {
    2902        7556 :         if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
    2903        2191 :             os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
    2904        3174 :                 return 0; /* Not a WPS Enrollee */
    2905             : 
    2906        2191 :         if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL)
    2907        1602 :                 return 0; /* Not using PBC */
    2908             : 
    2909         589 :         return 1;
    2910             : }
    2911             : 
    2912             : 
    2913        2686 : int eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
    2914             : {
    2915        4449 :         if (conf->identity_len != WSC_ID_ENROLLEE_LEN ||
    2916        1763 :             os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN))
    2917         923 :                 return 0; /* Not a WPS Enrollee */
    2918             : 
    2919        1763 :         if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL)
    2920         223 :                 return 0; /* Not using PIN */
    2921             : 
    2922        1540 :         return 1;
    2923             : }
    2924             : 
    2925             : 
    2926         590 : void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
    2927             : {
    2928         590 :         ext_password_free(sm->ext_pw_buf);
    2929         590 :         sm->ext_pw_buf = NULL;
    2930         590 :         sm->ext_pw = ext;
    2931         590 : }
    2932             : 
    2933             : 
    2934             : /**
    2935             :  * eap_set_anon_id - Set or add anonymous identity
    2936             :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
    2937             :  * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
    2938             :  * @len: Length of anonymous identity in octets
    2939             :  */
    2940          52 : void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
    2941             : {
    2942          52 :         if (sm->eapol_cb->set_anon_id)
    2943          52 :                 sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
    2944          52 : }
    2945             : 
    2946             : 
    2947         656 : int eap_peer_was_failure_expected(struct eap_sm *sm)
    2948             : {
    2949         656 :         return sm->expected_failure;
    2950             : }

Generated by: LCOV version 1.10