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