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 1475438200 Lines: 1141 1250 91.3 %
Date: 2016-10-02 Functions: 99 100 99.0 %

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

Generated by: LCOV version 1.10