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