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