Home | History | Annotate | Download | only in eapol_supp
      1 /*
      2  * EAPOL supplicant state machines
      3  * Copyright (c) 2004-2012, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "state_machine.h"
     13 #include "wpabuf.h"
     14 #include "eloop.h"
     15 #include "crypto/crypto.h"
     16 #include "crypto/md5.h"
     17 #include "common/eapol_common.h"
     18 #include "eap_peer/eap.h"
     19 #include "eap_peer/eap_config.h"
     20 #include "eap_peer/eap_proxy.h"
     21 #include "eapol_supp_sm.h"
     22 
     23 #define STATE_MACHINE_DATA struct eapol_sm
     24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
     25 
     26 
     27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
     28 
     29 /**
     30  * struct eapol_sm - Internal data for EAPOL state machines
     31  */
     32 struct eapol_sm {
     33 	/* Timers */
     34 	unsigned int authWhile;
     35 	unsigned int heldWhile;
     36 	unsigned int startWhen;
     37 	unsigned int idleWhile; /* for EAP state machine */
     38 	int timer_tick_enabled;
     39 
     40 	/* Global variables */
     41 	Boolean eapFail;
     42 	Boolean eapolEap;
     43 	Boolean eapSuccess;
     44 	Boolean initialize;
     45 	Boolean keyDone;
     46 	Boolean keyRun;
     47 	PortControl portControl;
     48 	Boolean portEnabled;
     49 	PortStatus suppPortStatus;  /* dot1xSuppControlledPortStatus */
     50 	Boolean portValid;
     51 	Boolean suppAbort;
     52 	Boolean suppFail;
     53 	Boolean suppStart;
     54 	Boolean suppSuccess;
     55 	Boolean suppTimeout;
     56 
     57 	/* Supplicant PAE state machine */
     58 	enum {
     59 		SUPP_PAE_UNKNOWN = 0,
     60 		SUPP_PAE_DISCONNECTED = 1,
     61 		SUPP_PAE_LOGOFF = 2,
     62 		SUPP_PAE_CONNECTING = 3,
     63 		SUPP_PAE_AUTHENTICATING = 4,
     64 		SUPP_PAE_AUTHENTICATED = 5,
     65 		/* unused(6) */
     66 		SUPP_PAE_HELD = 7,
     67 		SUPP_PAE_RESTART = 8,
     68 		SUPP_PAE_S_FORCE_AUTH = 9,
     69 		SUPP_PAE_S_FORCE_UNAUTH = 10
     70 	} SUPP_PAE_state; /* dot1xSuppPaeState */
     71 	/* Variables */
     72 	Boolean userLogoff;
     73 	Boolean logoffSent;
     74 	unsigned int startCount;
     75 	Boolean eapRestart;
     76 	PortControl sPortMode;
     77 	/* Constants */
     78 	unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
     79 	unsigned int startPeriod; /* dot1xSuppStartPeriod */
     80 	unsigned int maxStart; /* dot1xSuppMaxStart */
     81 
     82 	/* Key Receive state machine */
     83 	enum {
     84 		KEY_RX_UNKNOWN = 0,
     85 		KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
     86 	} KEY_RX_state;
     87 	/* Variables */
     88 	Boolean rxKey;
     89 
     90 	/* Supplicant Backend state machine */
     91 	enum {
     92 		SUPP_BE_UNKNOWN = 0,
     93 		SUPP_BE_INITIALIZE = 1,
     94 		SUPP_BE_IDLE = 2,
     95 		SUPP_BE_REQUEST = 3,
     96 		SUPP_BE_RECEIVE = 4,
     97 		SUPP_BE_RESPONSE = 5,
     98 		SUPP_BE_FAIL = 6,
     99 		SUPP_BE_TIMEOUT = 7,
    100 		SUPP_BE_SUCCESS = 8
    101 	} SUPP_BE_state; /* dot1xSuppBackendPaeState */
    102 	/* Variables */
    103 	Boolean eapNoResp;
    104 	Boolean eapReq;
    105 	Boolean eapResp;
    106 	/* Constants */
    107 	unsigned int authPeriod; /* dot1xSuppAuthPeriod */
    108 
    109 	/* Statistics */
    110 	unsigned int dot1xSuppEapolFramesRx;
    111 	unsigned int dot1xSuppEapolFramesTx;
    112 	unsigned int dot1xSuppEapolStartFramesTx;
    113 	unsigned int dot1xSuppEapolLogoffFramesTx;
    114 	unsigned int dot1xSuppEapolRespFramesTx;
    115 	unsigned int dot1xSuppEapolReqIdFramesRx;
    116 	unsigned int dot1xSuppEapolReqFramesRx;
    117 	unsigned int dot1xSuppInvalidEapolFramesRx;
    118 	unsigned int dot1xSuppEapLengthErrorFramesRx;
    119 	unsigned int dot1xSuppLastEapolFrameVersion;
    120 	unsigned char dot1xSuppLastEapolFrameSource[6];
    121 
    122 	/* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
    123 	Boolean changed;
    124 	struct eap_sm *eap;
    125 	struct eap_peer_config *config;
    126 	Boolean initial_req;
    127 	u8 *last_rx_key;
    128 	size_t last_rx_key_len;
    129 	struct wpabuf *eapReqData; /* for EAP */
    130 	Boolean altAccept; /* for EAP */
    131 	Boolean altReject; /* for EAP */
    132 	Boolean eapTriggerStart;
    133 	Boolean replay_counter_valid;
    134 	u8 last_replay_counter[16];
    135 	struct eapol_config conf;
    136 	struct eapol_ctx *ctx;
    137 	enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
    138 		cb_status;
    139 	Boolean cached_pmk;
    140 
    141 	Boolean unicast_key_received, broadcast_key_received;
    142 
    143 	Boolean force_authorized_update;
    144 
    145 #ifdef CONFIG_EAP_PROXY
    146 	Boolean use_eap_proxy;
    147 	struct eap_proxy_sm *eap_proxy;
    148 #endif /* CONFIG_EAP_PROXY */
    149 };
    150 
    151 
    152 static void eapol_sm_txLogoff(struct eapol_sm *sm);
    153 static void eapol_sm_txStart(struct eapol_sm *sm);
    154 static void eapol_sm_processKey(struct eapol_sm *sm);
    155 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
    156 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
    157 static void eapol_sm_abortSupp(struct eapol_sm *sm);
    158 static void eapol_sm_abort_cached(struct eapol_sm *sm);
    159 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
    160 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
    161 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
    162 
    163 
    164 /* Port Timers state machine - implemented as a function that will be called
    165  * once a second as a registered event loop timeout */
    166 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
    167 {
    168 	struct eapol_sm *sm = timeout_ctx;
    169 
    170 	if (sm->authWhile > 0) {
    171 		sm->authWhile--;
    172 		if (sm->authWhile == 0)
    173 			wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
    174 	}
    175 	if (sm->heldWhile > 0) {
    176 		sm->heldWhile--;
    177 		if (sm->heldWhile == 0)
    178 			wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
    179 	}
    180 	if (sm->startWhen > 0) {
    181 		sm->startWhen--;
    182 		if (sm->startWhen == 0)
    183 			wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
    184 	}
    185 	if (sm->idleWhile > 0) {
    186 		sm->idleWhile--;
    187 		if (sm->idleWhile == 0)
    188 			wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
    189 	}
    190 
    191 	if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
    192 		if (eloop_register_timeout(1, 0, eapol_port_timers_tick,
    193 					   eloop_ctx, sm) < 0)
    194 			sm->timer_tick_enabled = 0;
    195 	} else {
    196 		wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
    197 		sm->timer_tick_enabled = 0;
    198 	}
    199 	eapol_sm_step(sm);
    200 }
    201 
    202 
    203 static void eapol_enable_timer_tick(struct eapol_sm *sm)
    204 {
    205 	if (sm->timer_tick_enabled)
    206 		return;
    207 	wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
    208 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
    209 	if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
    210 		sm->timer_tick_enabled = 1;
    211 }
    212 
    213 
    214 SM_STATE(SUPP_PAE, LOGOFF)
    215 {
    216 	SM_ENTRY(SUPP_PAE, LOGOFF);
    217 	eapol_sm_txLogoff(sm);
    218 	sm->logoffSent = TRUE;
    219 	eapol_sm_set_port_unauthorized(sm);
    220 }
    221 
    222 
    223 SM_STATE(SUPP_PAE, DISCONNECTED)
    224 {
    225 	SM_ENTRY(SUPP_PAE, DISCONNECTED);
    226 	sm->sPortMode = Auto;
    227 	sm->startCount = 0;
    228 	sm->eapTriggerStart = FALSE;
    229 	sm->logoffSent = FALSE;
    230 	eapol_sm_set_port_unauthorized(sm);
    231 	sm->suppAbort = TRUE;
    232 
    233 	sm->unicast_key_received = FALSE;
    234 	sm->broadcast_key_received = FALSE;
    235 
    236 	/*
    237 	 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
    238 	 * allows the timer tick to be stopped more quickly when the port is
    239 	 * not enabled. Since this variable is used only within HELD state,
    240 	 * clearing it on initialization does not change actual state machine
    241 	 * behavior.
    242 	 */
    243 	sm->heldWhile = 0;
    244 }
    245 
    246 
    247 SM_STATE(SUPP_PAE, CONNECTING)
    248 {
    249 	int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
    250 		sm->SUPP_PAE_state == SUPP_PAE_HELD;
    251 	SM_ENTRY(SUPP_PAE, CONNECTING);
    252 
    253 	if (sm->eapTriggerStart)
    254 		send_start = 1;
    255 	if (sm->ctx->preauth)
    256 		send_start = 1;
    257 	sm->eapTriggerStart = FALSE;
    258 
    259 	if (send_start) {
    260 		sm->startWhen = sm->startPeriod;
    261 		sm->startCount++;
    262 	} else {
    263 		/*
    264 		 * Do not send EAPOL-Start immediately since in most cases,
    265 		 * Authenticator is going to start authentication immediately
    266 		 * after association and an extra EAPOL-Start is just going to
    267 		 * delay authentication. Use a short timeout to send the first
    268 		 * EAPOL-Start if Authenticator does not start authentication.
    269 		 */
    270 		if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
    271 			/* Reduce latency on starting WPS negotiation. */
    272 			wpa_printf(MSG_DEBUG,
    273 				   "EAPOL: Using shorter startWhen for WPS");
    274 			sm->startWhen = 1;
    275 		} else {
    276 			sm->startWhen = 2;
    277 		}
    278 	}
    279 	eapol_enable_timer_tick(sm);
    280 	sm->eapolEap = FALSE;
    281 	if (send_start)
    282 		eapol_sm_txStart(sm);
    283 }
    284 
    285 
    286 SM_STATE(SUPP_PAE, AUTHENTICATING)
    287 {
    288 	SM_ENTRY(SUPP_PAE, AUTHENTICATING);
    289 	sm->startCount = 0;
    290 	sm->suppSuccess = FALSE;
    291 	sm->suppFail = FALSE;
    292 	sm->suppTimeout = FALSE;
    293 	sm->keyRun = FALSE;
    294 	sm->keyDone = FALSE;
    295 	sm->suppStart = TRUE;
    296 }
    297 
    298 
    299 SM_STATE(SUPP_PAE, HELD)
    300 {
    301 	SM_ENTRY(SUPP_PAE, HELD);
    302 	sm->heldWhile = sm->heldPeriod;
    303 	eapol_enable_timer_tick(sm);
    304 	eapol_sm_set_port_unauthorized(sm);
    305 	sm->cb_status = EAPOL_CB_FAILURE;
    306 }
    307 
    308 
    309 SM_STATE(SUPP_PAE, AUTHENTICATED)
    310 {
    311 	SM_ENTRY(SUPP_PAE, AUTHENTICATED);
    312 	eapol_sm_set_port_authorized(sm);
    313 	sm->cb_status = EAPOL_CB_SUCCESS;
    314 }
    315 
    316 
    317 SM_STATE(SUPP_PAE, RESTART)
    318 {
    319 	SM_ENTRY(SUPP_PAE, RESTART);
    320 	sm->eapRestart = TRUE;
    321 	if (sm->altAccept) {
    322 		/*
    323 		 * Prevent EAP peer state machine from failing due to prior
    324 		 * external EAP success notification (altSuccess=TRUE in the
    325 		 * IDLE state could result in a transition to the FAILURE state.
    326 		 */
    327 		wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
    328 		sm->eapSuccess = FALSE;
    329 		sm->altAccept = FALSE;
    330 	}
    331 }
    332 
    333 
    334 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
    335 {
    336 	SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
    337 	eapol_sm_set_port_authorized(sm);
    338 	sm->sPortMode = ForceAuthorized;
    339 }
    340 
    341 
    342 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
    343 {
    344 	SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
    345 	eapol_sm_set_port_unauthorized(sm);
    346 	sm->sPortMode = ForceUnauthorized;
    347 	eapol_sm_txLogoff(sm);
    348 }
    349 
    350 
    351 SM_STEP(SUPP_PAE)
    352 {
    353 	if ((sm->userLogoff && !sm->logoffSent) &&
    354 	    !(sm->initialize || !sm->portEnabled))
    355 		SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
    356 	else if (((sm->portControl == Auto) &&
    357 		  (sm->sPortMode != sm->portControl)) ||
    358 		 sm->initialize || !sm->portEnabled)
    359 		SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
    360 	else if ((sm->portControl == ForceAuthorized) &&
    361 		 (sm->sPortMode != sm->portControl) &&
    362 		 !(sm->initialize || !sm->portEnabled))
    363 		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
    364 	else if ((sm->portControl == ForceUnauthorized) &&
    365 		 (sm->sPortMode != sm->portControl) &&
    366 		 !(sm->initialize || !sm->portEnabled))
    367 		SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
    368 	else switch (sm->SUPP_PAE_state) {
    369 	case SUPP_PAE_UNKNOWN:
    370 		break;
    371 	case SUPP_PAE_LOGOFF:
    372 		if (!sm->userLogoff)
    373 			SM_ENTER(SUPP_PAE, DISCONNECTED);
    374 		break;
    375 	case SUPP_PAE_DISCONNECTED:
    376 		SM_ENTER(SUPP_PAE, CONNECTING);
    377 		break;
    378 	case SUPP_PAE_CONNECTING:
    379 		if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
    380 			SM_ENTER(SUPP_PAE, CONNECTING);
    381 		else if (sm->startWhen == 0 &&
    382 			 sm->startCount >= sm->maxStart &&
    383 			 sm->portValid)
    384 			SM_ENTER(SUPP_PAE, AUTHENTICATED);
    385 		else if (sm->eapSuccess || sm->eapFail)
    386 			SM_ENTER(SUPP_PAE, AUTHENTICATING);
    387 		else if (sm->eapolEap)
    388 			SM_ENTER(SUPP_PAE, RESTART);
    389 		else if (sm->startWhen == 0 &&
    390 			 sm->startCount >= sm->maxStart &&
    391 			 !sm->portValid)
    392 			SM_ENTER(SUPP_PAE, HELD);
    393 		break;
    394 	case SUPP_PAE_AUTHENTICATING:
    395 		if (sm->eapSuccess && !sm->portValid &&
    396 		    sm->conf.accept_802_1x_keys &&
    397 		    sm->conf.required_keys == 0) {
    398 			wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
    399 				   "plaintext connection; no EAPOL-Key frames "
    400 				   "required");
    401 			sm->portValid = TRUE;
    402 			if (sm->ctx->eapol_done_cb)
    403 				sm->ctx->eapol_done_cb(sm->ctx->ctx);
    404 		}
    405 		if (sm->eapSuccess && sm->portValid)
    406 			SM_ENTER(SUPP_PAE, AUTHENTICATED);
    407 		else if (sm->eapFail || (sm->keyDone && !sm->portValid))
    408 			SM_ENTER(SUPP_PAE, HELD);
    409 		else if (sm->suppTimeout)
    410 			SM_ENTER(SUPP_PAE, CONNECTING);
    411 		else if (sm->eapTriggerStart)
    412 			SM_ENTER(SUPP_PAE, CONNECTING);
    413 		break;
    414 	case SUPP_PAE_HELD:
    415 		if (sm->heldWhile == 0)
    416 			SM_ENTER(SUPP_PAE, CONNECTING);
    417 		else if (sm->eapolEap)
    418 			SM_ENTER(SUPP_PAE, RESTART);
    419 		break;
    420 	case SUPP_PAE_AUTHENTICATED:
    421 		if (sm->eapolEap && sm->portValid)
    422 			SM_ENTER(SUPP_PAE, RESTART);
    423 		else if (!sm->portValid)
    424 			SM_ENTER(SUPP_PAE, DISCONNECTED);
    425 		break;
    426 	case SUPP_PAE_RESTART:
    427 		if (!sm->eapRestart)
    428 			SM_ENTER(SUPP_PAE, AUTHENTICATING);
    429 		break;
    430 	case SUPP_PAE_S_FORCE_AUTH:
    431 		break;
    432 	case SUPP_PAE_S_FORCE_UNAUTH:
    433 		break;
    434 	}
    435 }
    436 
    437 
    438 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
    439 {
    440 	SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
    441 }
    442 
    443 
    444 SM_STATE(KEY_RX, KEY_RECEIVE)
    445 {
    446 	SM_ENTRY(KEY_RX, KEY_RECEIVE);
    447 	eapol_sm_processKey(sm);
    448 	sm->rxKey = FALSE;
    449 }
    450 
    451 
    452 SM_STEP(KEY_RX)
    453 {
    454 	if (sm->initialize || !sm->portEnabled)
    455 		SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
    456 	switch (sm->KEY_RX_state) {
    457 	case KEY_RX_UNKNOWN:
    458 		break;
    459 	case KEY_RX_NO_KEY_RECEIVE:
    460 		if (sm->rxKey)
    461 			SM_ENTER(KEY_RX, KEY_RECEIVE);
    462 		break;
    463 	case KEY_RX_KEY_RECEIVE:
    464 		if (sm->rxKey)
    465 			SM_ENTER(KEY_RX, KEY_RECEIVE);
    466 		break;
    467 	}
    468 }
    469 
    470 
    471 SM_STATE(SUPP_BE, REQUEST)
    472 {
    473 	SM_ENTRY(SUPP_BE, REQUEST);
    474 	sm->authWhile = 0;
    475 	sm->eapReq = TRUE;
    476 	eapol_sm_getSuppRsp(sm);
    477 }
    478 
    479 
    480 SM_STATE(SUPP_BE, RESPONSE)
    481 {
    482 	SM_ENTRY(SUPP_BE, RESPONSE);
    483 	eapol_sm_txSuppRsp(sm);
    484 	sm->eapResp = FALSE;
    485 }
    486 
    487 
    488 SM_STATE(SUPP_BE, SUCCESS)
    489 {
    490 	SM_ENTRY(SUPP_BE, SUCCESS);
    491 	sm->keyRun = TRUE;
    492 	sm->suppSuccess = TRUE;
    493 
    494 #ifdef CONFIG_EAP_PROXY
    495 	if (sm->use_eap_proxy) {
    496 		if (eap_proxy_key_available(sm->eap_proxy)) {
    497 			u8 *session_id, *emsk;
    498 			size_t session_id_len, emsk_len;
    499 
    500 			/* New key received - clear IEEE 802.1X EAPOL-Key replay
    501 			 * counter */
    502 			sm->replay_counter_valid = FALSE;
    503 
    504 			session_id = eap_proxy_get_eap_session_id(
    505 				sm->eap_proxy, &session_id_len);
    506 			emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
    507 			if (sm->config->erp && session_id && emsk) {
    508 				eap_peer_erp_init(sm->eap, session_id,
    509 						  session_id_len, emsk,
    510 						  emsk_len);
    511 			} else {
    512 				os_free(session_id);
    513 				bin_clear_free(emsk, emsk_len);
    514 			}
    515 		}
    516 		return;
    517 	}
    518 #endif /* CONFIG_EAP_PROXY */
    519 
    520 	if (eap_key_available(sm->eap)) {
    521 		/* New key received - clear IEEE 802.1X EAPOL-Key replay
    522 		 * counter */
    523 		sm->replay_counter_valid = FALSE;
    524 	}
    525 }
    526 
    527 
    528 SM_STATE(SUPP_BE, FAIL)
    529 {
    530 	SM_ENTRY(SUPP_BE, FAIL);
    531 	sm->suppFail = TRUE;
    532 }
    533 
    534 
    535 SM_STATE(SUPP_BE, TIMEOUT)
    536 {
    537 	SM_ENTRY(SUPP_BE, TIMEOUT);
    538 	sm->suppTimeout = TRUE;
    539 }
    540 
    541 
    542 SM_STATE(SUPP_BE, IDLE)
    543 {
    544 	SM_ENTRY(SUPP_BE, IDLE);
    545 	sm->suppStart = FALSE;
    546 	sm->initial_req = TRUE;
    547 }
    548 
    549 
    550 SM_STATE(SUPP_BE, INITIALIZE)
    551 {
    552 	SM_ENTRY(SUPP_BE, INITIALIZE);
    553 	eapol_sm_abortSupp(sm);
    554 	sm->suppAbort = FALSE;
    555 
    556 	/*
    557 	 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
    558 	 * allows the timer tick to be stopped more quickly when the port is
    559 	 * not enabled. Since this variable is used only within RECEIVE state,
    560 	 * clearing it on initialization does not change actual state machine
    561 	 * behavior.
    562 	 */
    563 	sm->authWhile = 0;
    564 }
    565 
    566 
    567 SM_STATE(SUPP_BE, RECEIVE)
    568 {
    569 	SM_ENTRY(SUPP_BE, RECEIVE);
    570 	sm->authWhile = sm->authPeriod;
    571 	eapol_enable_timer_tick(sm);
    572 	sm->eapolEap = FALSE;
    573 	sm->eapNoResp = FALSE;
    574 	sm->initial_req = FALSE;
    575 }
    576 
    577 
    578 SM_STEP(SUPP_BE)
    579 {
    580 	if (sm->initialize || sm->suppAbort)
    581 		SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
    582 	else switch (sm->SUPP_BE_state) {
    583 	case SUPP_BE_UNKNOWN:
    584 		break;
    585 	case SUPP_BE_REQUEST:
    586 		/*
    587 		 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
    588 		 * and SUCCESS based on eapFail and eapSuccess, respectively.
    589 		 * However, IEEE Std 802.1X-2004 is also specifying that
    590 		 * eapNoResp should be set in conjunction with eapSuccess and
    591 		 * eapFail which would mean that more than one of the
    592 		 * transitions here would be activated at the same time.
    593 		 * Skipping RESPONSE and/or RECEIVE states in these cases can
    594 		 * cause problems and the direct transitions to do not seem
    595 		 * correct. Because of this, the conditions for these
    596 		 * transitions are verified only after eapNoResp. They are
    597 		 * unlikely to be used since eapNoResp should always be set if
    598 		 * either of eapSuccess or eapFail is set.
    599 		 */
    600 		if (sm->eapResp && sm->eapNoResp) {
    601 			wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
    602 				   "eapResp and eapNoResp set?!");
    603 		}
    604 		if (sm->eapResp)
    605 			SM_ENTER(SUPP_BE, RESPONSE);
    606 		else if (sm->eapNoResp)
    607 			SM_ENTER(SUPP_BE, RECEIVE);
    608 		else if (sm->eapFail)
    609 			SM_ENTER(SUPP_BE, FAIL);
    610 		else if (sm->eapSuccess)
    611 			SM_ENTER(SUPP_BE, SUCCESS);
    612 		break;
    613 	case SUPP_BE_RESPONSE:
    614 		SM_ENTER(SUPP_BE, RECEIVE);
    615 		break;
    616 	case SUPP_BE_SUCCESS:
    617 		SM_ENTER(SUPP_BE, IDLE);
    618 		break;
    619 	case SUPP_BE_FAIL:
    620 		SM_ENTER(SUPP_BE, IDLE);
    621 		break;
    622 	case SUPP_BE_TIMEOUT:
    623 		SM_ENTER(SUPP_BE, IDLE);
    624 		break;
    625 	case SUPP_BE_IDLE:
    626 		if (sm->eapFail && sm->suppStart)
    627 			SM_ENTER(SUPP_BE, FAIL);
    628 		else if (sm->eapolEap && sm->suppStart)
    629 			SM_ENTER(SUPP_BE, REQUEST);
    630 		else if (sm->eapSuccess && sm->suppStart)
    631 			SM_ENTER(SUPP_BE, SUCCESS);
    632 		break;
    633 	case SUPP_BE_INITIALIZE:
    634 		SM_ENTER(SUPP_BE, IDLE);
    635 		break;
    636 	case SUPP_BE_RECEIVE:
    637 		if (sm->eapolEap)
    638 			SM_ENTER(SUPP_BE, REQUEST);
    639 		else if (sm->eapFail)
    640 			SM_ENTER(SUPP_BE, FAIL);
    641 		else if (sm->authWhile == 0)
    642 			SM_ENTER(SUPP_BE, TIMEOUT);
    643 		else if (sm->eapSuccess)
    644 			SM_ENTER(SUPP_BE, SUCCESS);
    645 		break;
    646 	}
    647 }
    648 
    649 
    650 static void eapol_sm_txLogoff(struct eapol_sm *sm)
    651 {
    652 	wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
    653 	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
    654 			    IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
    655 	sm->dot1xSuppEapolLogoffFramesTx++;
    656 	sm->dot1xSuppEapolFramesTx++;
    657 }
    658 
    659 
    660 static void eapol_sm_txStart(struct eapol_sm *sm)
    661 {
    662 	wpa_printf(MSG_DEBUG, "EAPOL: txStart");
    663 	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
    664 			    IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
    665 	sm->dot1xSuppEapolStartFramesTx++;
    666 	sm->dot1xSuppEapolFramesTx++;
    667 }
    668 
    669 
    670 #define IEEE8021X_ENCR_KEY_LEN 32
    671 #define IEEE8021X_SIGN_KEY_LEN 32
    672 
    673 struct eap_key_data {
    674 	u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
    675 	u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
    676 };
    677 
    678 
    679 static void eapol_sm_processKey(struct eapol_sm *sm)
    680 {
    681 #ifndef CONFIG_FIPS
    682 	struct ieee802_1x_hdr *hdr;
    683 	struct ieee802_1x_eapol_key *key;
    684 	struct eap_key_data keydata;
    685 	u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
    686 #ifndef CONFIG_NO_RC4
    687 	u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
    688 #endif /* CONFIG_NO_RC4 */
    689 	int key_len, res, sign_key_len, encr_key_len;
    690 	u16 rx_key_length;
    691 	size_t plen;
    692 
    693 	wpa_printf(MSG_DEBUG, "EAPOL: processKey");
    694 	if (sm->last_rx_key == NULL)
    695 		return;
    696 
    697 	if (!sm->conf.accept_802_1x_keys) {
    698 		wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
    699 			   " even though this was not accepted - "
    700 			   "ignoring this packet");
    701 		return;
    702 	}
    703 
    704 	if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
    705 		return;
    706 	hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
    707 	key = (struct ieee802_1x_eapol_key *) (hdr + 1);
    708 	plen = be_to_host16(hdr->length);
    709 	if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
    710 		wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
    711 		return;
    712 	}
    713 	rx_key_length = WPA_GET_BE16(key->key_length);
    714 	wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
    715 		   "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
    716 		   hdr->version, hdr->type, be_to_host16(hdr->length),
    717 		   key->type, rx_key_length, key->key_index);
    718 
    719 	eapol_sm_notify_lower_layer_success(sm, 1);
    720 	sign_key_len = IEEE8021X_SIGN_KEY_LEN;
    721 	encr_key_len = IEEE8021X_ENCR_KEY_LEN;
    722 	res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
    723 	if (res < 0) {
    724 		wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
    725 			   "decrypting EAPOL-Key keys");
    726 		return;
    727 	}
    728 	if (res == 16) {
    729 		/* LEAP derives only 16 bytes of keying material. */
    730 		res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
    731 		if (res) {
    732 			wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
    733 				   "master key for decrypting EAPOL-Key keys");
    734 			return;
    735 		}
    736 		sign_key_len = 16;
    737 		encr_key_len = 16;
    738 		os_memcpy(keydata.sign_key, keydata.encr_key, 16);
    739 	} else if (res) {
    740 		wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
    741 			   "data for decrypting EAPOL-Key keys (res=%d)", res);
    742 		return;
    743 	}
    744 
    745 	/* The key replay_counter must increase when same master key */
    746 	if (sm->replay_counter_valid &&
    747 	    os_memcmp(sm->last_replay_counter, key->replay_counter,
    748 		      IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
    749 		wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
    750 			   "not increase - ignoring key");
    751 		wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
    752 			    sm->last_replay_counter,
    753 			    IEEE8021X_REPLAY_COUNTER_LEN);
    754 		wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
    755 			    key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
    756 		return;
    757 	}
    758 
    759 	/* Verify key signature (HMAC-MD5) */
    760 	os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
    761 	os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
    762 	hmac_md5(keydata.sign_key, sign_key_len,
    763 		 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
    764 		 key->key_signature);
    765 	if (os_memcmp_const(orig_key_sign, key->key_signature,
    766 			    IEEE8021X_KEY_SIGN_LEN) != 0) {
    767 		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
    768 			   "EAPOL-Key packet");
    769 		os_memcpy(key->key_signature, orig_key_sign,
    770 			  IEEE8021X_KEY_SIGN_LEN);
    771 		return;
    772 	}
    773 	wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
    774 
    775 	key_len = plen - sizeof(*key);
    776 	if (key_len > 32 || rx_key_length > 32) {
    777 		wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
    778 			   key_len ? key_len : rx_key_length);
    779 		return;
    780 	}
    781 	if (key_len == rx_key_length) {
    782 #ifdef CONFIG_NO_RC4
    783 		if (encr_key_len) {
    784 			/* otherwise unused */
    785 		}
    786 		wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build");
    787 		return;
    788 #else /* CONFIG_NO_RC4 */
    789 		os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
    790 		os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
    791 			  encr_key_len);
    792 		os_memcpy(datakey, key + 1, key_len);
    793 		rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
    794 			 datakey, key_len);
    795 		wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
    796 				datakey, key_len);
    797 #endif /* CONFIG_NO_RC4 */
    798 	} else if (key_len == 0) {
    799 		/*
    800 		 * IEEE 802.1X-2004 specifies that least significant Key Length
    801 		 * octets from MS-MPPE-Send-Key are used as the key if the key
    802 		 * data is not present. This seems to be meaning the beginning
    803 		 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
    804 		 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
    805 		 * Anyway, taking the beginning of the keying material from EAP
    806 		 * seems to interoperate with Authenticators.
    807 		 */
    808 		key_len = rx_key_length;
    809 		os_memcpy(datakey, keydata.encr_key, key_len);
    810 		wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
    811 				"material data encryption key",
    812 				datakey, key_len);
    813 	} else {
    814 		wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
    815 			   "(key_length=%d)", key_len, rx_key_length);
    816 		return;
    817 	}
    818 
    819 	sm->replay_counter_valid = TRUE;
    820 	os_memcpy(sm->last_replay_counter, key->replay_counter,
    821 		  IEEE8021X_REPLAY_COUNTER_LEN);
    822 
    823 	wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
    824 		   "len %d",
    825 		   key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
    826 		   "unicast" : "broadcast",
    827 		   key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
    828 
    829 	if (sm->ctx->set_wep_key &&
    830 	    sm->ctx->set_wep_key(sm->ctx->ctx,
    831 				 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
    832 				 key->key_index & IEEE8021X_KEY_INDEX_MASK,
    833 				 datakey, key_len) < 0) {
    834 		wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
    835 			   " driver.");
    836 	} else {
    837 		if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
    838 			sm->unicast_key_received = TRUE;
    839 		else
    840 			sm->broadcast_key_received = TRUE;
    841 
    842 		if ((sm->unicast_key_received ||
    843 		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
    844 		    (sm->broadcast_key_received ||
    845 		     !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
    846 		{
    847 			wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
    848 				   "frames received");
    849 			sm->portValid = TRUE;
    850 			if (sm->ctx->eapol_done_cb)
    851 				sm->ctx->eapol_done_cb(sm->ctx->ctx);
    852 		}
    853 	}
    854 #endif /* CONFIG_FIPS */
    855 }
    856 
    857 
    858 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
    859 {
    860 	wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
    861 	/* EAP layer processing; no special code is needed, since Supplicant
    862 	 * Backend state machine is waiting for eapNoResp or eapResp to be set
    863 	 * and these are only set in the EAP state machine when the processing
    864 	 * has finished. */
    865 }
    866 
    867 
    868 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
    869 {
    870 	struct wpabuf *resp;
    871 
    872 	wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
    873 
    874 #ifdef CONFIG_EAP_PROXY
    875 	if (sm->use_eap_proxy) {
    876 		/* Get EAP Response from EAP Proxy */
    877 		resp = eap_proxy_get_eapRespData(sm->eap_proxy);
    878 		if (resp == NULL) {
    879 			wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
    880 				   "response data not available");
    881 			return;
    882 		}
    883 	} else
    884 #endif /* CONFIG_EAP_PROXY */
    885 
    886 	resp = eap_get_eapRespData(sm->eap);
    887 	if (resp == NULL) {
    888 		wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
    889 			   "not available");
    890 		return;
    891 	}
    892 
    893 	/* Send EAP-Packet from the EAP layer to the Authenticator */
    894 	sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
    895 			    IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
    896 			    wpabuf_len(resp));
    897 
    898 	/* eapRespData is not used anymore, so free it here */
    899 	wpabuf_free(resp);
    900 
    901 	if (sm->initial_req)
    902 		sm->dot1xSuppEapolReqIdFramesRx++;
    903 	else
    904 		sm->dot1xSuppEapolReqFramesRx++;
    905 	sm->dot1xSuppEapolRespFramesTx++;
    906 	sm->dot1xSuppEapolFramesTx++;
    907 }
    908 
    909 
    910 static void eapol_sm_abortSupp(struct eapol_sm *sm)
    911 {
    912 	/* release system resources that may have been allocated for the
    913 	 * authentication session */
    914 	os_free(sm->last_rx_key);
    915 	sm->last_rx_key = NULL;
    916 	wpabuf_free(sm->eapReqData);
    917 	sm->eapReqData = NULL;
    918 	eap_sm_abort(sm->eap);
    919 #ifdef CONFIG_EAP_PROXY
    920 	eap_proxy_sm_abort(sm->eap_proxy);
    921 #endif /* CONFIG_EAP_PROXY */
    922 }
    923 
    924 
    925 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
    926 {
    927 	eapol_sm_step(timeout_ctx);
    928 }
    929 
    930 
    931 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
    932 {
    933 	int cb;
    934 
    935 	cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
    936 	sm->force_authorized_update = FALSE;
    937 	sm->suppPortStatus = Authorized;
    938 	if (cb && sm->ctx->port_cb)
    939 		sm->ctx->port_cb(sm->ctx->ctx, 1);
    940 }
    941 
    942 
    943 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
    944 {
    945 	int cb;
    946 
    947 	cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
    948 	sm->force_authorized_update = FALSE;
    949 	sm->suppPortStatus = Unauthorized;
    950 	if (cb && sm->ctx->port_cb)
    951 		sm->ctx->port_cb(sm->ctx->ctx, 0);
    952 }
    953 
    954 
    955 /**
    956  * eapol_sm_step - EAPOL state machine step function
    957  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
    958  *
    959  * This function is called to notify the state machine about changed external
    960  * variables. It will step through the EAPOL state machines in loop to process
    961  * all triggered state changes.
    962  */
    963 void eapol_sm_step(struct eapol_sm *sm)
    964 {
    965 	int i;
    966 
    967 	/* In theory, it should be ok to run this in loop until !changed.
    968 	 * However, it is better to use a limit on number of iterations to
    969 	 * allow events (e.g., SIGTERM) to stop the program cleanly if the
    970 	 * state machine were to generate a busy loop. */
    971 	for (i = 0; i < 100; i++) {
    972 		sm->changed = FALSE;
    973 		SM_STEP_RUN(SUPP_PAE);
    974 		SM_STEP_RUN(KEY_RX);
    975 		SM_STEP_RUN(SUPP_BE);
    976 #ifdef CONFIG_EAP_PROXY
    977 		if (sm->use_eap_proxy) {
    978 			/* Drive the EAP proxy state machine */
    979 			if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
    980 				sm->changed = TRUE;
    981 		} else
    982 #endif /* CONFIG_EAP_PROXY */
    983 		if (eap_peer_sm_step(sm->eap))
    984 			sm->changed = TRUE;
    985 		if (!sm->changed)
    986 			break;
    987 	}
    988 
    989 	if (sm->changed) {
    990 		/* restart EAPOL state machine step from timeout call in order
    991 		 * to allow other events to be processed. */
    992 		eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
    993 		eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
    994 	}
    995 
    996 	if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
    997 		enum eapol_supp_result result;
    998 		if (sm->cb_status == EAPOL_CB_SUCCESS)
    999 			result = EAPOL_SUPP_RESULT_SUCCESS;
   1000 		else if (eap_peer_was_failure_expected(sm->eap))
   1001 			result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
   1002 		else
   1003 			result = EAPOL_SUPP_RESULT_FAILURE;
   1004 		sm->cb_status = EAPOL_CB_IN_PROGRESS;
   1005 		sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
   1006 	}
   1007 }
   1008 
   1009 
   1010 #ifdef CONFIG_CTRL_IFACE
   1011 static const char *eapol_supp_pae_state(int state)
   1012 {
   1013 	switch (state) {
   1014 	case SUPP_PAE_LOGOFF:
   1015 		return "LOGOFF";
   1016 	case SUPP_PAE_DISCONNECTED:
   1017 		return "DISCONNECTED";
   1018 	case SUPP_PAE_CONNECTING:
   1019 		return "CONNECTING";
   1020 	case SUPP_PAE_AUTHENTICATING:
   1021 		return "AUTHENTICATING";
   1022 	case SUPP_PAE_HELD:
   1023 		return "HELD";
   1024 	case SUPP_PAE_AUTHENTICATED:
   1025 		return "AUTHENTICATED";
   1026 	case SUPP_PAE_RESTART:
   1027 		return "RESTART";
   1028 	default:
   1029 		return "UNKNOWN";
   1030 	}
   1031 }
   1032 
   1033 
   1034 static const char *eapol_supp_be_state(int state)
   1035 {
   1036 	switch (state) {
   1037 	case SUPP_BE_REQUEST:
   1038 		return "REQUEST";
   1039 	case SUPP_BE_RESPONSE:
   1040 		return "RESPONSE";
   1041 	case SUPP_BE_SUCCESS:
   1042 		return "SUCCESS";
   1043 	case SUPP_BE_FAIL:
   1044 		return "FAIL";
   1045 	case SUPP_BE_TIMEOUT:
   1046 		return "TIMEOUT";
   1047 	case SUPP_BE_IDLE:
   1048 		return "IDLE";
   1049 	case SUPP_BE_INITIALIZE:
   1050 		return "INITIALIZE";
   1051 	case SUPP_BE_RECEIVE:
   1052 		return "RECEIVE";
   1053 	default:
   1054 		return "UNKNOWN";
   1055 	}
   1056 }
   1057 
   1058 
   1059 static const char * eapol_port_status(PortStatus status)
   1060 {
   1061 	if (status == Authorized)
   1062 		return "Authorized";
   1063 	else
   1064 		return "Unauthorized";
   1065 }
   1066 #endif /* CONFIG_CTRL_IFACE */
   1067 
   1068 
   1069 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
   1070 static const char * eapol_port_control(PortControl ctrl)
   1071 {
   1072 	switch (ctrl) {
   1073 	case Auto:
   1074 		return "Auto";
   1075 	case ForceUnauthorized:
   1076 		return "ForceUnauthorized";
   1077 	case ForceAuthorized:
   1078 		return "ForceAuthorized";
   1079 	default:
   1080 		return "Unknown";
   1081 	}
   1082 }
   1083 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
   1084 
   1085 
   1086 /**
   1087  * eapol_sm_configure - Set EAPOL variables
   1088  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1089  * @heldPeriod: dot1xSuppHeldPeriod
   1090  * @authPeriod: dot1xSuppAuthPeriod
   1091  * @startPeriod: dot1xSuppStartPeriod
   1092  * @maxStart: dot1xSuppMaxStart
   1093  *
   1094  * Set configurable EAPOL state machine variables. Each variable can be set to
   1095  * the given value or ignored if set to -1 (to set only some of the variables).
   1096  */
   1097 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
   1098 			int startPeriod, int maxStart)
   1099 {
   1100 	if (sm == NULL)
   1101 		return;
   1102 	if (heldPeriod >= 0)
   1103 		sm->heldPeriod = heldPeriod;
   1104 	if (authPeriod >= 0)
   1105 		sm->authPeriod = authPeriod;
   1106 	if (startPeriod >= 0)
   1107 		sm->startPeriod = startPeriod;
   1108 	if (maxStart >= 0)
   1109 		sm->maxStart = maxStart;
   1110 }
   1111 
   1112 
   1113 /**
   1114  * eapol_sm_get_method_name - Get EAPOL method name
   1115  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1116  * Returns: Static string containing name of current eap method or NULL
   1117  */
   1118 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
   1119 {
   1120 	if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
   1121 	    sm->suppPortStatus != Authorized)
   1122 		return NULL;
   1123 
   1124 	return eap_sm_get_method_name(sm->eap);
   1125 }
   1126 
   1127 
   1128 #ifdef CONFIG_CTRL_IFACE
   1129 /**
   1130  * eapol_sm_get_status - Get EAPOL state machine status
   1131  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1132  * @buf: Buffer for status information
   1133  * @buflen: Maximum buffer length
   1134  * @verbose: Whether to include verbose status information
   1135  * Returns: Number of bytes written to buf.
   1136  *
   1137  * Query EAPOL state machine for status information. This function fills in a
   1138  * text area with current status information from the EAPOL state machine. If
   1139  * the buffer (buf) is not large enough, status information will be truncated
   1140  * to fit the buffer.
   1141  */
   1142 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
   1143 			int verbose)
   1144 {
   1145 	int len, ret;
   1146 	if (sm == NULL)
   1147 		return 0;
   1148 
   1149 	len = os_snprintf(buf, buflen,
   1150 			  "Supplicant PAE state=%s\n"
   1151 			  "suppPortStatus=%s\n",
   1152 			  eapol_supp_pae_state(sm->SUPP_PAE_state),
   1153 			  eapol_port_status(sm->suppPortStatus));
   1154 	if (os_snprintf_error(buflen, len))
   1155 		return 0;
   1156 
   1157 	if (verbose) {
   1158 		ret = os_snprintf(buf + len, buflen - len,
   1159 				  "heldPeriod=%u\n"
   1160 				  "authPeriod=%u\n"
   1161 				  "startPeriod=%u\n"
   1162 				  "maxStart=%u\n"
   1163 				  "portControl=%s\n"
   1164 				  "Supplicant Backend state=%s\n",
   1165 				  sm->heldPeriod,
   1166 				  sm->authPeriod,
   1167 				  sm->startPeriod,
   1168 				  sm->maxStart,
   1169 				  eapol_port_control(sm->portControl),
   1170 				  eapol_supp_be_state(sm->SUPP_BE_state));
   1171 		if (os_snprintf_error(buflen - len, ret))
   1172 			return len;
   1173 		len += ret;
   1174 	}
   1175 
   1176 #ifdef CONFIG_EAP_PROXY
   1177 	if (sm->use_eap_proxy)
   1178 		len += eap_proxy_sm_get_status(sm->eap_proxy,
   1179 					       buf + len, buflen - len,
   1180 					       verbose);
   1181 	else
   1182 #endif /* CONFIG_EAP_PROXY */
   1183 	len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
   1184 
   1185 	return len;
   1186 }
   1187 
   1188 
   1189 /**
   1190  * eapol_sm_get_mib - Get EAPOL state machine MIBs
   1191  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1192  * @buf: Buffer for MIB information
   1193  * @buflen: Maximum buffer length
   1194  * Returns: Number of bytes written to buf.
   1195  *
   1196  * Query EAPOL state machine for MIB information. This function fills in a
   1197  * text area with current MIB information from the EAPOL state machine. If
   1198  * the buffer (buf) is not large enough, MIB information will be truncated to
   1199  * fit the buffer.
   1200  */
   1201 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
   1202 {
   1203 	size_t len;
   1204 	int ret;
   1205 
   1206 	if (sm == NULL)
   1207 		return 0;
   1208 	ret = os_snprintf(buf, buflen,
   1209 			  "dot1xSuppPaeState=%d\n"
   1210 			  "dot1xSuppHeldPeriod=%u\n"
   1211 			  "dot1xSuppAuthPeriod=%u\n"
   1212 			  "dot1xSuppStartPeriod=%u\n"
   1213 			  "dot1xSuppMaxStart=%u\n"
   1214 			  "dot1xSuppSuppControlledPortStatus=%s\n"
   1215 			  "dot1xSuppBackendPaeState=%d\n",
   1216 			  sm->SUPP_PAE_state,
   1217 			  sm->heldPeriod,
   1218 			  sm->authPeriod,
   1219 			  sm->startPeriod,
   1220 			  sm->maxStart,
   1221 			  sm->suppPortStatus == Authorized ?
   1222 			  "Authorized" : "Unauthorized",
   1223 			  sm->SUPP_BE_state);
   1224 
   1225 	if (os_snprintf_error(buflen, ret))
   1226 		return 0;
   1227 	len = ret;
   1228 
   1229 	ret = os_snprintf(buf + len, buflen - len,
   1230 			  "dot1xSuppEapolFramesRx=%u\n"
   1231 			  "dot1xSuppEapolFramesTx=%u\n"
   1232 			  "dot1xSuppEapolStartFramesTx=%u\n"
   1233 			  "dot1xSuppEapolLogoffFramesTx=%u\n"
   1234 			  "dot1xSuppEapolRespFramesTx=%u\n"
   1235 			  "dot1xSuppEapolReqIdFramesRx=%u\n"
   1236 			  "dot1xSuppEapolReqFramesRx=%u\n"
   1237 			  "dot1xSuppInvalidEapolFramesRx=%u\n"
   1238 			  "dot1xSuppEapLengthErrorFramesRx=%u\n"
   1239 			  "dot1xSuppLastEapolFrameVersion=%u\n"
   1240 			  "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
   1241 			  sm->dot1xSuppEapolFramesRx,
   1242 			  sm->dot1xSuppEapolFramesTx,
   1243 			  sm->dot1xSuppEapolStartFramesTx,
   1244 			  sm->dot1xSuppEapolLogoffFramesTx,
   1245 			  sm->dot1xSuppEapolRespFramesTx,
   1246 			  sm->dot1xSuppEapolReqIdFramesRx,
   1247 			  sm->dot1xSuppEapolReqFramesRx,
   1248 			  sm->dot1xSuppInvalidEapolFramesRx,
   1249 			  sm->dot1xSuppEapLengthErrorFramesRx,
   1250 			  sm->dot1xSuppLastEapolFrameVersion,
   1251 			  MAC2STR(sm->dot1xSuppLastEapolFrameSource));
   1252 
   1253 	if (os_snprintf_error(buflen - len, ret))
   1254 		return len;
   1255 	len += ret;
   1256 
   1257 	return len;
   1258 }
   1259 #endif /* CONFIG_CTRL_IFACE */
   1260 
   1261 
   1262 /**
   1263  * eapol_sm_rx_eapol - Process received EAPOL frames
   1264  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1265  * @src: Source MAC address of the EAPOL packet
   1266  * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
   1267  * @len: Length of the EAPOL frame
   1268  * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
   1269  * -1 failure
   1270  */
   1271 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
   1272 		      size_t len)
   1273 {
   1274 	const struct ieee802_1x_hdr *hdr;
   1275 	const struct ieee802_1x_eapol_key *key;
   1276 	int data_len;
   1277 	int res = 1;
   1278 	size_t plen;
   1279 
   1280 	if (sm == NULL)
   1281 		return 0;
   1282 	sm->dot1xSuppEapolFramesRx++;
   1283 	if (len < sizeof(*hdr)) {
   1284 		sm->dot1xSuppInvalidEapolFramesRx++;
   1285 		return 0;
   1286 	}
   1287 	hdr = (const struct ieee802_1x_hdr *) buf;
   1288 	sm->dot1xSuppLastEapolFrameVersion = hdr->version;
   1289 	os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
   1290 	if (hdr->version < EAPOL_VERSION) {
   1291 		/* TODO: backwards compatibility */
   1292 	}
   1293 	plen = be_to_host16(hdr->length);
   1294 	if (plen > len - sizeof(*hdr)) {
   1295 		sm->dot1xSuppEapLengthErrorFramesRx++;
   1296 		return 0;
   1297 	}
   1298 #ifdef CONFIG_WPS
   1299 	if (sm->conf.wps && sm->conf.workaround &&
   1300 	    plen < len - sizeof(*hdr) &&
   1301 	    hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
   1302 	    len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
   1303 		const struct eap_hdr *ehdr =
   1304 			(const struct eap_hdr *) (hdr + 1);
   1305 		u16 elen;
   1306 
   1307 		elen = be_to_host16(ehdr->length);
   1308 		if (elen > plen && elen <= len - sizeof(*hdr)) {
   1309 			/*
   1310 			 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
   1311 			 * packets with too short EAPOL header length field
   1312 			 * (14 octets). This is fixed in firmware Ver.1.49.
   1313 			 * As a workaround, fix the EAPOL header based on the
   1314 			 * correct length in the EAP packet.
   1315 			 */
   1316 			wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
   1317 				   "payload length based on EAP header: "
   1318 				   "%d -> %d", (int) plen, elen);
   1319 			plen = elen;
   1320 		}
   1321 	}
   1322 #endif /* CONFIG_WPS */
   1323 	data_len = plen + sizeof(*hdr);
   1324 
   1325 	switch (hdr->type) {
   1326 	case IEEE802_1X_TYPE_EAP_PACKET:
   1327 		if (sm->conf.workaround) {
   1328 			/*
   1329 			 * An AP has been reported to send out EAP message with
   1330 			 * undocumented code 10 at some point near the
   1331 			 * completion of EAP authentication. This can result in
   1332 			 * issues with the unexpected EAP message triggering
   1333 			 * restart of EAPOL authentication. Avoid this by
   1334 			 * skipping the message without advancing the state
   1335 			 * machine.
   1336 			 */
   1337 			const struct eap_hdr *ehdr =
   1338 				(const struct eap_hdr *) (hdr + 1);
   1339 			if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
   1340 				wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
   1341 				break;
   1342 			}
   1343 		}
   1344 
   1345 		if (sm->cached_pmk) {
   1346 			/* Trying to use PMKSA caching, but Authenticator did
   1347 			 * not seem to have a matching entry. Need to restart
   1348 			 * EAPOL state machines.
   1349 			 */
   1350 			eapol_sm_abort_cached(sm);
   1351 		}
   1352 		wpabuf_free(sm->eapReqData);
   1353 		sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
   1354 		if (sm->eapReqData) {
   1355 			wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
   1356 				   "frame");
   1357 			sm->eapolEap = TRUE;
   1358 #ifdef CONFIG_EAP_PROXY
   1359 			if (sm->use_eap_proxy) {
   1360 				eap_proxy_packet_update(
   1361 					sm->eap_proxy,
   1362 					wpabuf_mhead_u8(sm->eapReqData),
   1363 					wpabuf_len(sm->eapReqData));
   1364 				wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
   1365 					   "EAP Req updated");
   1366 			}
   1367 #endif /* CONFIG_EAP_PROXY */
   1368 			eapol_sm_step(sm);
   1369 		}
   1370 		break;
   1371 	case IEEE802_1X_TYPE_EAPOL_KEY:
   1372 		if (plen < sizeof(*key)) {
   1373 			wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
   1374 				   "frame received");
   1375 			break;
   1376 		}
   1377 		key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
   1378 		if (key->type == EAPOL_KEY_TYPE_WPA ||
   1379 		    key->type == EAPOL_KEY_TYPE_RSN) {
   1380 			/* WPA Supplicant takes care of this frame. */
   1381 			wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
   1382 				   "frame in EAPOL state machines");
   1383 			res = 0;
   1384 			break;
   1385 		}
   1386 		if (key->type != EAPOL_KEY_TYPE_RC4) {
   1387 			wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
   1388 				   "EAPOL-Key type %d", key->type);
   1389 			break;
   1390 		}
   1391 		os_free(sm->last_rx_key);
   1392 		sm->last_rx_key = os_malloc(data_len);
   1393 		if (sm->last_rx_key) {
   1394 			wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
   1395 				   "frame");
   1396 			os_memcpy(sm->last_rx_key, buf, data_len);
   1397 			sm->last_rx_key_len = data_len;
   1398 			sm->rxKey = TRUE;
   1399 			eapol_sm_step(sm);
   1400 		}
   1401 		break;
   1402 #ifdef CONFIG_MACSEC
   1403 	case IEEE802_1X_TYPE_EAPOL_MKA:
   1404 		wpa_printf(MSG_EXCESSIVE,
   1405 			   "EAPOL type %d will be handled by MKA",
   1406 			   hdr->type);
   1407 		break;
   1408 #endif /* CONFIG_MACSEC */
   1409 	default:
   1410 		wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
   1411 			   hdr->type);
   1412 		sm->dot1xSuppInvalidEapolFramesRx++;
   1413 		break;
   1414 	}
   1415 
   1416 	return res;
   1417 }
   1418 
   1419 
   1420 /**
   1421  * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
   1422  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1423  *
   1424  * Notify EAPOL state machine about transmitted EAPOL packet from an external
   1425  * component, e.g., WPA. This will update the statistics.
   1426  */
   1427 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
   1428 {
   1429 	if (sm)
   1430 		sm->dot1xSuppEapolFramesTx++;
   1431 }
   1432 
   1433 
   1434 /**
   1435  * eapol_sm_notify_portEnabled - Notification about portEnabled change
   1436  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1437  * @enabled: New portEnabled value
   1438  *
   1439  * Notify EAPOL state machine about new portEnabled value.
   1440  */
   1441 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
   1442 {
   1443 	if (sm == NULL)
   1444 		return;
   1445 	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
   1446 		   "portEnabled=%d", enabled);
   1447 	if (sm->portEnabled != enabled)
   1448 		sm->force_authorized_update = TRUE;
   1449 	sm->portEnabled = enabled;
   1450 	eapol_sm_step(sm);
   1451 }
   1452 
   1453 
   1454 /**
   1455  * eapol_sm_notify_portValid - Notification about portValid change
   1456  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1457  * @valid: New portValid value
   1458  *
   1459  * Notify EAPOL state machine about new portValid value.
   1460  */
   1461 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
   1462 {
   1463 	if (sm == NULL)
   1464 		return;
   1465 	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
   1466 		   "portValid=%d", valid);
   1467 	sm->portValid = valid;
   1468 	eapol_sm_step(sm);
   1469 }
   1470 
   1471 
   1472 /**
   1473  * eapol_sm_notify_eap_success - Notification of external EAP success trigger
   1474  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1475  * @success: %TRUE = set success, %FALSE = clear success
   1476  *
   1477  * Notify the EAPOL state machine that external event has forced EAP state to
   1478  * success (success = %TRUE). This can be cleared by setting success = %FALSE.
   1479  *
   1480  * This function is called to update EAP state when WPA-PSK key handshake has
   1481  * been completed successfully since WPA-PSK does not use EAP state machine.
   1482  */
   1483 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
   1484 {
   1485 	if (sm == NULL)
   1486 		return;
   1487 	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
   1488 		   "EAP success=%d", success);
   1489 	sm->eapSuccess = success;
   1490 	sm->altAccept = success;
   1491 	if (success)
   1492 		eap_notify_success(sm->eap);
   1493 	eapol_sm_step(sm);
   1494 }
   1495 
   1496 
   1497 /**
   1498  * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
   1499  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1500  * @fail: %TRUE = set failure, %FALSE = clear failure
   1501  *
   1502  * Notify EAPOL state machine that external event has forced EAP state to
   1503  * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
   1504  */
   1505 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
   1506 {
   1507 	if (sm == NULL)
   1508 		return;
   1509 	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
   1510 		   "EAP fail=%d", fail);
   1511 	sm->eapFail = fail;
   1512 	sm->altReject = fail;
   1513 	eapol_sm_step(sm);
   1514 }
   1515 
   1516 
   1517 /**
   1518  * eapol_sm_notify_config - Notification of EAPOL configuration change
   1519  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1520  * @config: Pointer to current network EAP configuration
   1521  * @conf: Pointer to EAPOL configuration data
   1522  *
   1523  * Notify EAPOL state machine that configuration has changed. config will be
   1524  * stored as a backpointer to network configuration. This can be %NULL to clear
   1525  * the stored pointed. conf will be copied to local EAPOL/EAP configuration
   1526  * data. If conf is %NULL, this part of the configuration change will be
   1527  * skipped.
   1528  */
   1529 void eapol_sm_notify_config(struct eapol_sm *sm,
   1530 			    struct eap_peer_config *config,
   1531 			    const struct eapol_config *conf)
   1532 {
   1533 	if (sm == NULL)
   1534 		return;
   1535 
   1536 	sm->config = config;
   1537 #ifdef CONFIG_EAP_PROXY
   1538 	sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
   1539 #endif /* CONFIG_EAP_PROXY */
   1540 
   1541 	if (conf == NULL)
   1542 		return;
   1543 
   1544 	sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
   1545 	sm->conf.required_keys = conf->required_keys;
   1546 	sm->conf.fast_reauth = conf->fast_reauth;
   1547 	sm->conf.workaround = conf->workaround;
   1548 	sm->conf.wps = conf->wps;
   1549 #ifdef CONFIG_EAP_PROXY
   1550 	if (sm->use_eap_proxy) {
   1551 		/* Using EAP Proxy, so skip EAP state machine update */
   1552 		return;
   1553 	}
   1554 #endif /* CONFIG_EAP_PROXY */
   1555 	if (sm->eap) {
   1556 		eap_set_fast_reauth(sm->eap, conf->fast_reauth);
   1557 		eap_set_workaround(sm->eap, conf->workaround);
   1558 		eap_set_force_disabled(sm->eap, conf->eap_disabled);
   1559 		eap_set_external_sim(sm->eap, conf->external_sim);
   1560 	}
   1561 }
   1562 
   1563 
   1564 /**
   1565  * eapol_sm_get_key - Get master session key (MSK) from EAP
   1566  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1567  * @key: Pointer for key buffer
   1568  * @len: Number of bytes to copy to key
   1569  * Returns: 0 on success (len of key available), maximum available key len
   1570  * (>0) if key is available but it is shorter than len, or -1 on failure.
   1571  *
   1572  * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
   1573  * is available only after a successful authentication.
   1574  */
   1575 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
   1576 {
   1577 	const u8 *eap_key;
   1578 	size_t eap_len;
   1579 
   1580 #ifdef CONFIG_EAP_PROXY
   1581 	if (sm && sm->use_eap_proxy) {
   1582 		/* Get key from EAP proxy */
   1583 		if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
   1584 			wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
   1585 			return -1;
   1586 		}
   1587 		eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
   1588 		if (eap_key == NULL) {
   1589 			wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
   1590 				   "eapKeyData");
   1591 			return -1;
   1592 		}
   1593 		goto key_fetched;
   1594 	}
   1595 #endif /* CONFIG_EAP_PROXY */
   1596 	if (sm == NULL || !eap_key_available(sm->eap)) {
   1597 		wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
   1598 		return -1;
   1599 	}
   1600 	eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
   1601 	if (eap_key == NULL) {
   1602 		wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
   1603 		return -1;
   1604 	}
   1605 #ifdef CONFIG_EAP_PROXY
   1606 key_fetched:
   1607 #endif /* CONFIG_EAP_PROXY */
   1608 	if (len > eap_len) {
   1609 		wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
   1610 			   "available (len=%lu)",
   1611 			   (unsigned long) len, (unsigned long) eap_len);
   1612 		return eap_len;
   1613 	}
   1614 	os_memcpy(key, eap_key, len);
   1615 	wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
   1616 		   (unsigned long) len);
   1617 	return 0;
   1618 }
   1619 
   1620 
   1621 /**
   1622  * eapol_sm_get_session_id - Get EAP Session-Id
   1623  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1624  * @len: Pointer to variable that will be set to number of bytes in the session
   1625  * Returns: Pointer to the EAP Session-Id or %NULL on failure
   1626  *
   1627  * The Session-Id is available only after a successful authentication.
   1628  */
   1629 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
   1630 {
   1631 	if (sm == NULL || !eap_key_available(sm->eap)) {
   1632 		wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
   1633 		return NULL;
   1634 	}
   1635 	return eap_get_eapSessionId(sm->eap, len);
   1636 }
   1637 
   1638 
   1639 /**
   1640  * eapol_sm_notify_logoff - Notification of logon/logoff commands
   1641  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1642  * @logoff: Whether command was logoff
   1643  *
   1644  * Notify EAPOL state machines that user requested logon/logoff.
   1645  */
   1646 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
   1647 {
   1648 	if (sm) {
   1649 		sm->userLogoff = logoff;
   1650 		if (!logoff) {
   1651 			/* If there is a delayed txStart queued, start now. */
   1652 			sm->startWhen = 0;
   1653 		}
   1654 		eapol_sm_step(sm);
   1655 	}
   1656 }
   1657 
   1658 
   1659 /**
   1660  * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
   1661  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1662  *
   1663  * Notify EAPOL state machines that PMKSA caching was successful. This is used
   1664  * to move EAPOL and EAP state machines into authenticated/successful state.
   1665  */
   1666 void eapol_sm_notify_cached(struct eapol_sm *sm)
   1667 {
   1668 	if (sm == NULL)
   1669 		return;
   1670 	wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
   1671 	sm->eapSuccess = TRUE;
   1672 	eap_notify_success(sm->eap);
   1673 	eapol_sm_step(sm);
   1674 }
   1675 
   1676 
   1677 /**
   1678  * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
   1679  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1680  *
   1681  * Notify EAPOL state machines if PMKSA caching is used.
   1682  */
   1683 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm)
   1684 {
   1685 	if (sm == NULL)
   1686 		return;
   1687 	wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
   1688 	sm->cached_pmk = TRUE;
   1689 }
   1690 
   1691 
   1692 static void eapol_sm_abort_cached(struct eapol_sm *sm)
   1693 {
   1694 	wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
   1695 		   "doing full EAP authentication");
   1696 	if (sm == NULL)
   1697 		return;
   1698 	sm->cached_pmk = FALSE;
   1699 	sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
   1700 	eapol_sm_set_port_unauthorized(sm);
   1701 
   1702 	/* Make sure we do not start sending EAPOL-Start frames first, but
   1703 	 * instead move to RESTART state to start EAPOL authentication. */
   1704 	sm->startWhen = 3;
   1705 	eapol_enable_timer_tick(sm);
   1706 
   1707 	if (sm->ctx->aborted_cached)
   1708 		sm->ctx->aborted_cached(sm->ctx->ctx);
   1709 }
   1710 
   1711 
   1712 /**
   1713  * eapol_sm_register_scard_ctx - Notification of smart card context
   1714  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1715  * @ctx: Context data for smart card operations
   1716  *
   1717  * Notify EAPOL state machines of context data for smart card operations. This
   1718  * context data will be used as a parameter for scard_*() functions.
   1719  */
   1720 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
   1721 {
   1722 	if (sm) {
   1723 		sm->ctx->scard_ctx = ctx;
   1724 		eap_register_scard_ctx(sm->eap, ctx);
   1725 	}
   1726 }
   1727 
   1728 
   1729 /**
   1730  * eapol_sm_notify_portControl - Notification of portControl changes
   1731  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1732  * @portControl: New value for portControl variable
   1733  *
   1734  * Notify EAPOL state machines that portControl variable has changed.
   1735  */
   1736 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
   1737 {
   1738 	if (sm == NULL)
   1739 		return;
   1740 	wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
   1741 		   "portControl=%s", eapol_port_control(portControl));
   1742 	sm->portControl = portControl;
   1743 	eapol_sm_step(sm);
   1744 }
   1745 
   1746 
   1747 /**
   1748  * eapol_sm_notify_ctrl_attached - Notification of attached monitor
   1749  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1750  *
   1751  * Notify EAPOL state machines that a monitor was attached to the control
   1752  * interface to trigger re-sending of pending requests for user input.
   1753  */
   1754 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
   1755 {
   1756 	if (sm == NULL)
   1757 		return;
   1758 	eap_sm_notify_ctrl_attached(sm->eap);
   1759 }
   1760 
   1761 
   1762 /**
   1763  * eapol_sm_notify_ctrl_response - Notification of received user input
   1764  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1765  *
   1766  * Notify EAPOL state machines that a control response, i.e., user
   1767  * input, was received in order to trigger retrying of a pending EAP request.
   1768  */
   1769 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
   1770 {
   1771 	if (sm == NULL)
   1772 		return;
   1773 	if (sm->eapReqData && !sm->eapReq) {
   1774 		wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
   1775 			   "input) notification - retrying pending EAP "
   1776 			   "Request");
   1777 		sm->eapolEap = TRUE;
   1778 		sm->eapReq = TRUE;
   1779 		eapol_sm_step(sm);
   1780 	}
   1781 }
   1782 
   1783 
   1784 /**
   1785  * eapol_sm_request_reauth - Request reauthentication
   1786  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1787  *
   1788  * This function can be used to request EAPOL reauthentication, e.g., when the
   1789  * current PMKSA entry is nearing expiration.
   1790  */
   1791 void eapol_sm_request_reauth(struct eapol_sm *sm)
   1792 {
   1793 	if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
   1794 		return;
   1795 	eapol_sm_txStart(sm);
   1796 }
   1797 
   1798 
   1799 /**
   1800  * eapol_sm_notify_lower_layer_success - Notification of lower layer success
   1801  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1802  * @in_eapol_sm: Whether the caller is already running inside EAPOL state
   1803  * machine loop (eapol_sm_step())
   1804  *
   1805  * Notify EAPOL (and EAP) state machines that a lower layer has detected a
   1806  * successful authentication. This is used to recover from dropped EAP-Success
   1807  * messages.
   1808  */
   1809 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
   1810 {
   1811 	if (sm == NULL)
   1812 		return;
   1813 	eap_notify_lower_layer_success(sm->eap);
   1814 	if (!in_eapol_sm)
   1815 		eapol_sm_step(sm);
   1816 }
   1817 
   1818 
   1819 /**
   1820  * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
   1821  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   1822  */
   1823 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
   1824 {
   1825 	if (sm)
   1826 		eap_invalidate_cached_session(sm->eap);
   1827 }
   1828 
   1829 
   1830 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
   1831 {
   1832 	struct eapol_sm *sm = ctx;
   1833 	return sm ? sm->config : NULL;
   1834 }
   1835 
   1836 
   1837 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
   1838 {
   1839 	struct eapol_sm *sm = ctx;
   1840 	if (sm == NULL || sm->eapReqData == NULL)
   1841 		return NULL;
   1842 
   1843 	return sm->eapReqData;
   1844 }
   1845 
   1846 
   1847 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
   1848 {
   1849 	struct eapol_sm *sm = ctx;
   1850 	if (sm == NULL)
   1851 		return FALSE;
   1852 	switch (variable) {
   1853 	case EAPOL_eapSuccess:
   1854 		return sm->eapSuccess;
   1855 	case EAPOL_eapRestart:
   1856 		return sm->eapRestart;
   1857 	case EAPOL_eapFail:
   1858 		return sm->eapFail;
   1859 	case EAPOL_eapResp:
   1860 		return sm->eapResp;
   1861 	case EAPOL_eapNoResp:
   1862 		return sm->eapNoResp;
   1863 	case EAPOL_eapReq:
   1864 		return sm->eapReq;
   1865 	case EAPOL_portEnabled:
   1866 		return sm->portEnabled;
   1867 	case EAPOL_altAccept:
   1868 		return sm->altAccept;
   1869 	case EAPOL_altReject:
   1870 		return sm->altReject;
   1871 	case EAPOL_eapTriggerStart:
   1872 		return sm->eapTriggerStart;
   1873 	}
   1874 	return FALSE;
   1875 }
   1876 
   1877 
   1878 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
   1879 			      Boolean value)
   1880 {
   1881 	struct eapol_sm *sm = ctx;
   1882 	if (sm == NULL)
   1883 		return;
   1884 	switch (variable) {
   1885 	case EAPOL_eapSuccess:
   1886 		sm->eapSuccess = value;
   1887 		break;
   1888 	case EAPOL_eapRestart:
   1889 		sm->eapRestart = value;
   1890 		break;
   1891 	case EAPOL_eapFail:
   1892 		sm->eapFail = value;
   1893 		break;
   1894 	case EAPOL_eapResp:
   1895 		sm->eapResp = value;
   1896 		break;
   1897 	case EAPOL_eapNoResp:
   1898 		sm->eapNoResp = value;
   1899 		break;
   1900 	case EAPOL_eapReq:
   1901 		sm->eapReq = value;
   1902 		break;
   1903 	case EAPOL_portEnabled:
   1904 		sm->portEnabled = value;
   1905 		break;
   1906 	case EAPOL_altAccept:
   1907 		sm->altAccept = value;
   1908 		break;
   1909 	case EAPOL_altReject:
   1910 		sm->altReject = value;
   1911 		break;
   1912 	case EAPOL_eapTriggerStart:
   1913 		sm->eapTriggerStart = value;
   1914 		break;
   1915 	}
   1916 }
   1917 
   1918 
   1919 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
   1920 {
   1921 	struct eapol_sm *sm = ctx;
   1922 	if (sm == NULL)
   1923 		return 0;
   1924 	switch (variable) {
   1925 	case EAPOL_idleWhile:
   1926 		return sm->idleWhile;
   1927 	}
   1928 	return 0;
   1929 }
   1930 
   1931 
   1932 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
   1933 			     unsigned int value)
   1934 {
   1935 	struct eapol_sm *sm = ctx;
   1936 	if (sm == NULL)
   1937 		return;
   1938 	switch (variable) {
   1939 	case EAPOL_idleWhile:
   1940 		sm->idleWhile = value;
   1941 		if (sm->idleWhile > 0)
   1942 			eapol_enable_timer_tick(sm);
   1943 		break;
   1944 	}
   1945 }
   1946 
   1947 
   1948 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
   1949 {
   1950 #ifndef CONFIG_NO_CONFIG_BLOBS
   1951 	struct eapol_sm *sm = ctx;
   1952 	if (sm && sm->ctx && sm->ctx->set_config_blob)
   1953 		sm->ctx->set_config_blob(sm->ctx->ctx, blob);
   1954 #endif /* CONFIG_NO_CONFIG_BLOBS */
   1955 }
   1956 
   1957 
   1958 static const struct wpa_config_blob *
   1959 eapol_sm_get_config_blob(void *ctx, const char *name)
   1960 {
   1961 #ifndef CONFIG_NO_CONFIG_BLOBS
   1962 	struct eapol_sm *sm = ctx;
   1963 	if (sm && sm->ctx && sm->ctx->get_config_blob)
   1964 		return sm->ctx->get_config_blob(sm->ctx->ctx, name);
   1965 	else
   1966 		return NULL;
   1967 #else /* CONFIG_NO_CONFIG_BLOBS */
   1968 	return NULL;
   1969 #endif /* CONFIG_NO_CONFIG_BLOBS */
   1970 }
   1971 
   1972 
   1973 static void eapol_sm_notify_pending(void *ctx)
   1974 {
   1975 	struct eapol_sm *sm = ctx;
   1976 	if (sm == NULL)
   1977 		return;
   1978 	if (sm->eapReqData && !sm->eapReq) {
   1979 		wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
   1980 			   "state machine - retrying pending EAP Request");
   1981 		sm->eapolEap = TRUE;
   1982 		sm->eapReq = TRUE;
   1983 		eapol_sm_step(sm);
   1984 	}
   1985 }
   1986 
   1987 
   1988 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
   1989 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
   1990 				      const char *txt)
   1991 {
   1992 	struct eapol_sm *sm = ctx;
   1993 	wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
   1994 	if (sm->ctx->eap_param_needed)
   1995 		sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
   1996 }
   1997 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
   1998 #define eapol_sm_eap_param_needed NULL
   1999 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
   2000 
   2001 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
   2002 				 const char *altsubject[],
   2003 				 int num_altsubject, const char *cert_hash,
   2004 				 const struct wpabuf *cert)
   2005 {
   2006 	struct eapol_sm *sm = ctx;
   2007 	if (sm->ctx->cert_cb)
   2008 		sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, altsubject,
   2009 				 num_altsubject, cert_hash, cert);
   2010 }
   2011 
   2012 
   2013 static void eapol_sm_notify_status(void *ctx, const char *status,
   2014 				   const char *parameter)
   2015 {
   2016 	struct eapol_sm *sm = ctx;
   2017 
   2018 	if (sm->ctx->status_cb)
   2019 		sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
   2020 }
   2021 
   2022 
   2023 static void eapol_sm_notify_eap_error(void *ctx, int error_code)
   2024 {
   2025 	struct eapol_sm *sm = ctx;
   2026 
   2027 	if (sm->ctx->eap_error_cb)
   2028 		sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
   2029 }
   2030 
   2031 
   2032 #ifdef CONFIG_EAP_PROXY
   2033 
   2034 static void eapol_sm_eap_proxy_cb(void *ctx)
   2035 {
   2036 	struct eapol_sm *sm = ctx;
   2037 
   2038 	if (sm->ctx->eap_proxy_cb)
   2039 		sm->ctx->eap_proxy_cb(sm->ctx->ctx);
   2040 }
   2041 
   2042 
   2043 static void
   2044 eapol_sm_eap_proxy_notify_sim_status(void *ctx,
   2045 				     enum eap_proxy_sim_state sim_state)
   2046 {
   2047 	struct eapol_sm *sm = ctx;
   2048 
   2049 	if (sm->ctx->eap_proxy_notify_sim_status)
   2050 		sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state);
   2051 }
   2052 
   2053 #endif /* CONFIG_EAP_PROXY */
   2054 
   2055 
   2056 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
   2057 {
   2058 	struct eapol_sm *sm = ctx;
   2059 
   2060 	if (sm->ctx->set_anon_id)
   2061 		sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
   2062 }
   2063 
   2064 
   2065 static const struct eapol_callbacks eapol_cb =
   2066 {
   2067 	eapol_sm_get_config,
   2068 	eapol_sm_get_bool,
   2069 	eapol_sm_set_bool,
   2070 	eapol_sm_get_int,
   2071 	eapol_sm_set_int,
   2072 	eapol_sm_get_eapReqData,
   2073 	eapol_sm_set_config_blob,
   2074 	eapol_sm_get_config_blob,
   2075 	eapol_sm_notify_pending,
   2076 	eapol_sm_eap_param_needed,
   2077 	eapol_sm_notify_cert,
   2078 	eapol_sm_notify_status,
   2079 	eapol_sm_notify_eap_error,
   2080 #ifdef CONFIG_EAP_PROXY
   2081 	eapol_sm_eap_proxy_cb,
   2082 	eapol_sm_eap_proxy_notify_sim_status,
   2083 	eapol_sm_get_eap_proxy_imsi,
   2084 #endif /* CONFIG_EAP_PROXY */
   2085 	eapol_sm_set_anon_id
   2086 };
   2087 
   2088 
   2089 /**
   2090  * eapol_sm_init - Initialize EAPOL state machine
   2091  * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
   2092  * and EAPOL state machine will free it in eapol_sm_deinit()
   2093  * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
   2094  *
   2095  * Allocate and initialize an EAPOL state machine.
   2096  */
   2097 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
   2098 {
   2099 	struct eapol_sm *sm;
   2100 	struct eap_config conf;
   2101 	sm = os_zalloc(sizeof(*sm));
   2102 	if (sm == NULL)
   2103 		return NULL;
   2104 	sm->ctx = ctx;
   2105 
   2106 	sm->portControl = Auto;
   2107 
   2108 	/* Supplicant PAE state machine */
   2109 	sm->heldPeriod = 60;
   2110 	sm->startPeriod = 30;
   2111 	sm->maxStart = 3;
   2112 
   2113 	/* Supplicant Backend state machine */
   2114 	sm->authPeriod = 30;
   2115 
   2116 	os_memset(&conf, 0, sizeof(conf));
   2117 	conf.opensc_engine_path = ctx->opensc_engine_path;
   2118 	conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
   2119 	conf.pkcs11_module_path = ctx->pkcs11_module_path;
   2120 	conf.openssl_ciphers = ctx->openssl_ciphers;
   2121 	conf.wps = ctx->wps;
   2122 	conf.cert_in_cb = ctx->cert_in_cb;
   2123 
   2124 	sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
   2125 	if (sm->eap == NULL) {
   2126 		os_free(sm);
   2127 		return NULL;
   2128 	}
   2129 
   2130 #ifdef CONFIG_EAP_PROXY
   2131 	sm->use_eap_proxy = FALSE;
   2132 	sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
   2133 	if (sm->eap_proxy == NULL) {
   2134 		wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
   2135 	}
   2136 #endif /* CONFIG_EAP_PROXY */
   2137 
   2138 	/* Initialize EAPOL state machines */
   2139 	sm->force_authorized_update = TRUE;
   2140 	sm->initialize = TRUE;
   2141 	eapol_sm_step(sm);
   2142 	sm->initialize = FALSE;
   2143 	eapol_sm_step(sm);
   2144 
   2145 	if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0)
   2146 		sm->timer_tick_enabled = 1;
   2147 
   2148 	return sm;
   2149 }
   2150 
   2151 
   2152 /**
   2153  * eapol_sm_deinit - Deinitialize EAPOL state machine
   2154  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
   2155  *
   2156  * Deinitialize and free EAPOL state machine.
   2157  */
   2158 void eapol_sm_deinit(struct eapol_sm *sm)
   2159 {
   2160 	if (sm == NULL)
   2161 		return;
   2162 	eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
   2163 	eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
   2164 	eap_peer_sm_deinit(sm->eap);
   2165 #ifdef CONFIG_EAP_PROXY
   2166 	eap_proxy_deinit(sm->eap_proxy);
   2167 #endif /* CONFIG_EAP_PROXY */
   2168 	os_free(sm->last_rx_key);
   2169 	wpabuf_free(sm->eapReqData);
   2170 	os_free(sm->ctx);
   2171 	os_free(sm);
   2172 }
   2173 
   2174 
   2175 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
   2176 			     struct ext_password_data *ext)
   2177 {
   2178 	if (sm && sm->eap)
   2179 		eap_sm_set_ext_pw_ctx(sm->eap, ext);
   2180 }
   2181 
   2182 
   2183 int eapol_sm_failed(struct eapol_sm *sm)
   2184 {
   2185 	if (sm == NULL)
   2186 		return 0;
   2187 	return !sm->eapSuccess && sm->eapFail;
   2188 }
   2189 
   2190 
   2191 #ifdef CONFIG_EAP_PROXY
   2192 int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len)
   2193 {
   2194 	struct eapol_sm *sm = ctx;
   2195 
   2196 	if (sm->eap_proxy == NULL)
   2197 		return -1;
   2198 	return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len);
   2199 }
   2200 #endif /* CONFIG_EAP_PROXY */
   2201 
   2202 
   2203 void eapol_sm_erp_flush(struct eapol_sm *sm)
   2204 {
   2205 	if (sm)
   2206 		eap_peer_erp_free_keys(sm->eap);
   2207 }
   2208 
   2209 
   2210 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
   2211 {
   2212 #ifdef CONFIG_ERP
   2213 	if (!sm)
   2214 		return NULL;
   2215 	return eap_peer_build_erp_reauth_start(sm->eap, 0);
   2216 #else /* CONFIG_ERP */
   2217 	return NULL;
   2218 #endif /* CONFIG_ERP */
   2219 }
   2220 
   2221 
   2222 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
   2223 				 size_t len)
   2224 {
   2225 #ifdef CONFIG_ERP
   2226 	if (!sm)
   2227 		return;
   2228 	eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
   2229 #endif /* CONFIG_ERP */
   2230 }
   2231 
   2232 
   2233 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
   2234 {
   2235 #ifdef CONFIG_ERP
   2236 	if (!sm)
   2237 		return -1;
   2238 	return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
   2239 #else /* CONFIG_ERP */
   2240 	return -1;
   2241 #endif /* CONFIG_ERP */
   2242 }
   2243 
   2244 
   2245 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
   2246 			  const u8 **username, size_t *username_len,
   2247 			  const u8 **realm, size_t *realm_len,
   2248 			  u16 *erp_next_seq_num, const u8 **rrk,
   2249 			  size_t *rrk_len)
   2250 {
   2251 #ifdef CONFIG_ERP
   2252 	if (!sm)
   2253 		return -1;
   2254 	return eap_peer_get_erp_info(sm->eap, config, username, username_len,
   2255 				     realm, realm_len, erp_next_seq_num, rrk,
   2256 				     rrk_len);
   2257 #else /* CONFIG_ERP */
   2258 	return -1;
   2259 #endif /* CONFIG_ERP */
   2260 }
   2261