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