2 * EAPOL supplicant state machines
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "state_machine.h"
15 #include "crypto/crypto.h"
16 #include "crypto/md5.h"
17 #include "common/eapol_common.h"
18 #include "eap_peer/eap.h"
19 #include "eap_peer/eap_config.h"
20 #include "eap_peer/eap_proxy.h"
21 #include "eapol_supp_sm.h"
23 #define STATE_MACHINE_DATA struct eapol_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
30 * struct eapol_sm - Internal data for EAPOL state machines
34 unsigned int authWhile;
35 unsigned int heldWhile;
36 unsigned int startWhen;
37 unsigned int idleWhile; /* for EAP state machine */
38 int timer_tick_enabled;
40 /* Global variables */
47 PortControl portControl;
49 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
57 /* Supplicant PAE state machine */
60 SUPP_PAE_DISCONNECTED = 1,
62 SUPP_PAE_CONNECTING = 3,
63 SUPP_PAE_AUTHENTICATING = 4,
64 SUPP_PAE_AUTHENTICATED = 5,
68 SUPP_PAE_S_FORCE_AUTH = 9,
69 SUPP_PAE_S_FORCE_UNAUTH = 10
70 } SUPP_PAE_state; /* dot1xSuppPaeState */
74 unsigned int startCount;
76 PortControl sPortMode;
78 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
79 unsigned int startPeriod; /* dot1xSuppStartPeriod */
80 unsigned int maxStart; /* dot1xSuppMaxStart */
82 /* Key Receive state machine */
85 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
90 /* Supplicant Backend state machine */
93 SUPP_BE_INITIALIZE = 1,
101 } SUPP_BE_state; /* dot1xSuppBackendPaeState */
107 unsigned int authPeriod; /* dot1xSuppAuthPeriod */
110 unsigned int dot1xSuppEapolFramesRx;
111 unsigned int dot1xSuppEapolFramesTx;
112 unsigned int dot1xSuppEapolStartFramesTx;
113 unsigned int dot1xSuppEapolLogoffFramesTx;
114 unsigned int dot1xSuppEapolRespFramesTx;
115 unsigned int dot1xSuppEapolReqIdFramesRx;
116 unsigned int dot1xSuppEapolReqFramesRx;
117 unsigned int dot1xSuppInvalidEapolFramesRx;
118 unsigned int dot1xSuppEapLengthErrorFramesRx;
119 unsigned int dot1xSuppLastEapolFrameVersion;
120 unsigned char dot1xSuppLastEapolFrameSource[6];
122 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
125 struct eap_peer_config *config;
128 size_t last_rx_key_len;
129 struct wpabuf *eapReqData; /* for EAP */
130 Boolean altAccept; /* for EAP */
131 Boolean altReject; /* for EAP */
132 Boolean eapTriggerStart;
133 Boolean replay_counter_valid;
134 u8 last_replay_counter[16];
135 struct eapol_config conf;
136 struct eapol_ctx *ctx;
137 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
141 Boolean unicast_key_received, broadcast_key_received;
143 Boolean force_authorized_update;
145 #ifdef CONFIG_EAP_PROXY
146 Boolean use_eap_proxy;
147 struct eap_proxy_sm *eap_proxy;
148 #endif /* CONFIG_EAP_PROXY */
152 static void eapol_sm_txLogoff(struct eapol_sm *sm);
153 static void eapol_sm_txStart(struct eapol_sm *sm);
154 static void eapol_sm_processKey(struct eapol_sm *sm);
155 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
156 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
157 static void eapol_sm_abortSupp(struct eapol_sm *sm);
158 static void eapol_sm_abort_cached(struct eapol_sm *sm);
159 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
160 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
161 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
164 /* Port Timers state machine - implemented as a function that will be called
165 * once a second as a registered event loop timeout */
166 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
168 struct eapol_sm *sm = timeout_ctx;
170 if (sm->authWhile > 0) {
172 if (sm->authWhile == 0)
173 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
175 if (sm->heldWhile > 0) {
177 if (sm->heldWhile == 0)
178 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
180 if (sm->startWhen > 0) {
182 if (sm->startWhen == 0)
183 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
185 if (sm->idleWhile > 0) {
187 if (sm->idleWhile == 0)
188 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
191 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
192 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
195 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
196 sm->timer_tick_enabled = 0;
202 static void eapol_enable_timer_tick(struct eapol_sm *sm)
204 if (sm->timer_tick_enabled)
206 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
207 sm->timer_tick_enabled = 1;
208 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
209 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
213 SM_STATE(SUPP_PAE, LOGOFF)
215 SM_ENTRY(SUPP_PAE, LOGOFF);
216 eapol_sm_txLogoff(sm);
217 sm->logoffSent = TRUE;
218 eapol_sm_set_port_unauthorized(sm);
222 SM_STATE(SUPP_PAE, DISCONNECTED)
224 SM_ENTRY(SUPP_PAE, DISCONNECTED);
225 sm->sPortMode = Auto;
227 sm->eapTriggerStart = FALSE;
228 sm->logoffSent = FALSE;
229 eapol_sm_set_port_unauthorized(sm);
230 sm->suppAbort = TRUE;
232 sm->unicast_key_received = FALSE;
233 sm->broadcast_key_received = FALSE;
236 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
237 * allows the timer tick to be stopped more quickly when the port is
238 * not enabled. Since this variable is used only within HELD state,
239 * clearing it on initialization does not change actual state machine
246 SM_STATE(SUPP_PAE, CONNECTING)
248 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
249 sm->SUPP_PAE_state == SUPP_PAE_HELD;
250 SM_ENTRY(SUPP_PAE, CONNECTING);
252 if (sm->eapTriggerStart)
254 if (sm->ctx->preauth)
256 sm->eapTriggerStart = FALSE;
259 sm->startWhen = sm->startPeriod;
263 * Do not send EAPOL-Start immediately since in most cases,
264 * Authenticator is going to start authentication immediately
265 * after association and an extra EAPOL-Start is just going to
266 * delay authentication. Use a short timeout to send the first
267 * EAPOL-Start if Authenticator does not start authentication.
269 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
270 /* Reduce latency on starting WPS negotiation. */
271 wpa_printf(MSG_DEBUG,
272 "EAPOL: Using shorter startWhen for WPS");
278 eapol_enable_timer_tick(sm);
279 sm->eapolEap = FALSE;
281 eapol_sm_txStart(sm);
285 SM_STATE(SUPP_PAE, AUTHENTICATING)
287 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
289 sm->suppSuccess = FALSE;
290 sm->suppFail = FALSE;
291 sm->suppTimeout = FALSE;
294 sm->suppStart = TRUE;
298 SM_STATE(SUPP_PAE, HELD)
300 SM_ENTRY(SUPP_PAE, HELD);
301 sm->heldWhile = sm->heldPeriod;
302 eapol_enable_timer_tick(sm);
303 eapol_sm_set_port_unauthorized(sm);
304 sm->cb_status = EAPOL_CB_FAILURE;
308 SM_STATE(SUPP_PAE, AUTHENTICATED)
310 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
311 eapol_sm_set_port_authorized(sm);
312 sm->cb_status = EAPOL_CB_SUCCESS;
316 SM_STATE(SUPP_PAE, RESTART)
318 SM_ENTRY(SUPP_PAE, RESTART);
319 sm->eapRestart = TRUE;
322 * Prevent EAP peer state machine from failing due to prior
323 * external EAP success notification (altSuccess=TRUE in the
324 * IDLE state could result in a transition to the FAILURE state.
326 wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
327 sm->eapSuccess = FALSE;
328 sm->altAccept = FALSE;
333 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
335 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
336 eapol_sm_set_port_authorized(sm);
337 sm->sPortMode = ForceAuthorized;
341 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
343 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
344 eapol_sm_set_port_unauthorized(sm);
345 sm->sPortMode = ForceUnauthorized;
346 eapol_sm_txLogoff(sm);
352 if ((sm->userLogoff && !sm->logoffSent) &&
353 !(sm->initialize || !sm->portEnabled))
354 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
355 else if (((sm->portControl == Auto) &&
356 (sm->sPortMode != sm->portControl)) ||
357 sm->initialize || !sm->portEnabled)
358 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
359 else if ((sm->portControl == ForceAuthorized) &&
360 (sm->sPortMode != sm->portControl) &&
361 !(sm->initialize || !sm->portEnabled))
362 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
363 else if ((sm->portControl == ForceUnauthorized) &&
364 (sm->sPortMode != sm->portControl) &&
365 !(sm->initialize || !sm->portEnabled))
366 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
367 else switch (sm->SUPP_PAE_state) {
368 case SUPP_PAE_UNKNOWN:
370 case SUPP_PAE_LOGOFF:
372 SM_ENTER(SUPP_PAE, DISCONNECTED);
374 case SUPP_PAE_DISCONNECTED:
375 SM_ENTER(SUPP_PAE, CONNECTING);
377 case SUPP_PAE_CONNECTING:
378 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
379 SM_ENTER(SUPP_PAE, CONNECTING);
380 else if (sm->startWhen == 0 &&
381 sm->startCount >= sm->maxStart &&
383 SM_ENTER(SUPP_PAE, AUTHENTICATED);
384 else if (sm->eapSuccess || sm->eapFail)
385 SM_ENTER(SUPP_PAE, AUTHENTICATING);
386 else if (sm->eapolEap)
387 SM_ENTER(SUPP_PAE, RESTART);
388 else if (sm->startWhen == 0 &&
389 sm->startCount >= sm->maxStart &&
391 SM_ENTER(SUPP_PAE, HELD);
393 case SUPP_PAE_AUTHENTICATING:
394 if (sm->eapSuccess && !sm->portValid &&
395 sm->conf.accept_802_1x_keys &&
396 sm->conf.required_keys == 0) {
397 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
398 "plaintext connection; no EAPOL-Key frames "
400 sm->portValid = TRUE;
401 if (sm->ctx->eapol_done_cb)
402 sm->ctx->eapol_done_cb(sm->ctx->ctx);
404 if (sm->eapSuccess && sm->portValid)
405 SM_ENTER(SUPP_PAE, AUTHENTICATED);
406 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
407 SM_ENTER(SUPP_PAE, HELD);
408 else if (sm->suppTimeout)
409 SM_ENTER(SUPP_PAE, CONNECTING);
410 else if (sm->eapTriggerStart)
411 SM_ENTER(SUPP_PAE, CONNECTING);
414 if (sm->heldWhile == 0)
415 SM_ENTER(SUPP_PAE, CONNECTING);
416 else if (sm->eapolEap)
417 SM_ENTER(SUPP_PAE, RESTART);
419 case SUPP_PAE_AUTHENTICATED:
420 if (sm->eapolEap && sm->portValid)
421 SM_ENTER(SUPP_PAE, RESTART);
422 else if (!sm->portValid)
423 SM_ENTER(SUPP_PAE, DISCONNECTED);
425 case SUPP_PAE_RESTART:
427 SM_ENTER(SUPP_PAE, AUTHENTICATING);
429 case SUPP_PAE_S_FORCE_AUTH:
431 case SUPP_PAE_S_FORCE_UNAUTH:
437 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
439 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
443 SM_STATE(KEY_RX, KEY_RECEIVE)
445 SM_ENTRY(KEY_RX, KEY_RECEIVE);
446 eapol_sm_processKey(sm);
453 if (sm->initialize || !sm->portEnabled)
454 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
455 switch (sm->KEY_RX_state) {
458 case KEY_RX_NO_KEY_RECEIVE:
460 SM_ENTER(KEY_RX, KEY_RECEIVE);
462 case KEY_RX_KEY_RECEIVE:
464 SM_ENTER(KEY_RX, KEY_RECEIVE);
470 SM_STATE(SUPP_BE, REQUEST)
472 SM_ENTRY(SUPP_BE, REQUEST);
475 eapol_sm_getSuppRsp(sm);
479 SM_STATE(SUPP_BE, RESPONSE)
481 SM_ENTRY(SUPP_BE, RESPONSE);
482 eapol_sm_txSuppRsp(sm);
487 SM_STATE(SUPP_BE, SUCCESS)
489 SM_ENTRY(SUPP_BE, SUCCESS);
491 sm->suppSuccess = TRUE;
493 #ifdef CONFIG_EAP_PROXY
494 if (sm->use_eap_proxy) {
495 if (eap_proxy_key_available(sm->eap_proxy)) {
496 u8 *session_id, *emsk;
497 size_t session_id_len, emsk_len;
499 /* New key received - clear IEEE 802.1X EAPOL-Key replay
501 sm->replay_counter_valid = FALSE;
503 session_id = eap_proxy_get_eap_session_id(
504 sm->eap_proxy, &session_id_len);
505 emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
506 if (sm->config->erp && session_id && emsk) {
507 eap_peer_erp_init(sm->eap, session_id,
508 session_id_len, emsk,
512 bin_clear_free(emsk, emsk_len);
517 #endif /* CONFIG_EAP_PROXY */
519 if (eap_key_available(sm->eap)) {
520 /* New key received - clear IEEE 802.1X EAPOL-Key replay
522 sm->replay_counter_valid = FALSE;
527 SM_STATE(SUPP_BE, FAIL)
529 SM_ENTRY(SUPP_BE, FAIL);
534 SM_STATE(SUPP_BE, TIMEOUT)
536 SM_ENTRY(SUPP_BE, TIMEOUT);
537 sm->suppTimeout = TRUE;
541 SM_STATE(SUPP_BE, IDLE)
543 SM_ENTRY(SUPP_BE, IDLE);
544 sm->suppStart = FALSE;
545 sm->initial_req = TRUE;
549 SM_STATE(SUPP_BE, INITIALIZE)
551 SM_ENTRY(SUPP_BE, INITIALIZE);
552 eapol_sm_abortSupp(sm);
553 sm->suppAbort = FALSE;
556 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
557 * allows the timer tick to be stopped more quickly when the port is
558 * not enabled. Since this variable is used only within RECEIVE state,
559 * clearing it on initialization does not change actual state machine
566 SM_STATE(SUPP_BE, RECEIVE)
568 SM_ENTRY(SUPP_BE, RECEIVE);
569 sm->authWhile = sm->authPeriod;
570 eapol_enable_timer_tick(sm);
571 sm->eapolEap = FALSE;
572 sm->eapNoResp = FALSE;
573 sm->initial_req = FALSE;
579 if (sm->initialize || sm->suppAbort)
580 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
581 else switch (sm->SUPP_BE_state) {
582 case SUPP_BE_UNKNOWN:
584 case SUPP_BE_REQUEST:
586 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
587 * and SUCCESS based on eapFail and eapSuccess, respectively.
588 * However, IEEE Std 802.1X-2004 is also specifying that
589 * eapNoResp should be set in conjunction with eapSuccess and
590 * eapFail which would mean that more than one of the
591 * transitions here would be activated at the same time.
592 * Skipping RESPONSE and/or RECEIVE states in these cases can
593 * cause problems and the direct transitions to do not seem
594 * correct. Because of this, the conditions for these
595 * transitions are verified only after eapNoResp. They are
596 * unlikely to be used since eapNoResp should always be set if
597 * either of eapSuccess or eapFail is set.
599 if (sm->eapResp && sm->eapNoResp) {
600 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
601 "eapResp and eapNoResp set?!");
604 SM_ENTER(SUPP_BE, RESPONSE);
605 else if (sm->eapNoResp)
606 SM_ENTER(SUPP_BE, RECEIVE);
607 else if (sm->eapFail)
608 SM_ENTER(SUPP_BE, FAIL);
609 else if (sm->eapSuccess)
610 SM_ENTER(SUPP_BE, SUCCESS);
612 case SUPP_BE_RESPONSE:
613 SM_ENTER(SUPP_BE, RECEIVE);
615 case SUPP_BE_SUCCESS:
616 SM_ENTER(SUPP_BE, IDLE);
619 SM_ENTER(SUPP_BE, IDLE);
621 case SUPP_BE_TIMEOUT:
622 SM_ENTER(SUPP_BE, IDLE);
625 if (sm->eapFail && sm->suppStart)
626 SM_ENTER(SUPP_BE, FAIL);
627 else if (sm->eapolEap && sm->suppStart)
628 SM_ENTER(SUPP_BE, REQUEST);
629 else if (sm->eapSuccess && sm->suppStart)
630 SM_ENTER(SUPP_BE, SUCCESS);
632 case SUPP_BE_INITIALIZE:
633 SM_ENTER(SUPP_BE, IDLE);
635 case SUPP_BE_RECEIVE:
637 SM_ENTER(SUPP_BE, REQUEST);
638 else if (sm->eapFail)
639 SM_ENTER(SUPP_BE, FAIL);
640 else if (sm->authWhile == 0)
641 SM_ENTER(SUPP_BE, TIMEOUT);
642 else if (sm->eapSuccess)
643 SM_ENTER(SUPP_BE, SUCCESS);
649 static void eapol_sm_txLogoff(struct eapol_sm *sm)
651 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
652 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
653 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
654 sm->dot1xSuppEapolLogoffFramesTx++;
655 sm->dot1xSuppEapolFramesTx++;
659 static void eapol_sm_txStart(struct eapol_sm *sm)
661 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
662 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
663 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
664 sm->dot1xSuppEapolStartFramesTx++;
665 sm->dot1xSuppEapolFramesTx++;
669 #define IEEE8021X_ENCR_KEY_LEN 32
670 #define IEEE8021X_SIGN_KEY_LEN 32
672 struct eap_key_data {
673 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
674 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
678 static void eapol_sm_processKey(struct eapol_sm *sm)
681 struct ieee802_1x_hdr *hdr;
682 struct ieee802_1x_eapol_key *key;
683 struct eap_key_data keydata;
684 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
685 #ifndef CONFIG_NO_RC4
686 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
687 #endif /* CONFIG_NO_RC4 */
688 int key_len, res, sign_key_len, encr_key_len;
692 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
693 if (sm->last_rx_key == NULL)
696 if (!sm->conf.accept_802_1x_keys) {
697 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
698 " even though this was not accepted - "
699 "ignoring this packet");
703 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
705 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
706 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
707 plen = be_to_host16(hdr->length);
708 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
709 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
712 rx_key_length = WPA_GET_BE16(key->key_length);
713 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
714 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
715 hdr->version, hdr->type, be_to_host16(hdr->length),
716 key->type, rx_key_length, key->key_index);
718 eapol_sm_notify_lower_layer_success(sm, 1);
719 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
720 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
721 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
723 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
724 "decrypting EAPOL-Key keys");
728 /* LEAP derives only 16 bytes of keying material. */
729 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
731 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
732 "master key for decrypting EAPOL-Key keys");
737 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
739 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
740 "data for decrypting EAPOL-Key keys (res=%d)", res);
744 /* The key replay_counter must increase when same master key */
745 if (sm->replay_counter_valid &&
746 os_memcmp(sm->last_replay_counter, key->replay_counter,
747 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
748 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
749 "not increase - ignoring key");
750 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
751 sm->last_replay_counter,
752 IEEE8021X_REPLAY_COUNTER_LEN);
753 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
754 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
758 /* Verify key signature (HMAC-MD5) */
759 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
760 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
761 hmac_md5(keydata.sign_key, sign_key_len,
762 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
764 if (os_memcmp_const(orig_key_sign, key->key_signature,
765 IEEE8021X_KEY_SIGN_LEN) != 0) {
766 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
768 os_memcpy(key->key_signature, orig_key_sign,
769 IEEE8021X_KEY_SIGN_LEN);
772 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
774 key_len = plen - sizeof(*key);
775 if (key_len > 32 || rx_key_length > 32) {
776 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
777 key_len ? key_len : rx_key_length);
780 if (key_len == rx_key_length) {
783 /* otherwise unused */
785 wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build");
787 #else /* CONFIG_NO_RC4 */
788 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
789 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
791 os_memcpy(datakey, key + 1, key_len);
792 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
794 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
796 #endif /* CONFIG_NO_RC4 */
797 } else if (key_len == 0) {
799 * IEEE 802.1X-2004 specifies that least significant Key Length
800 * octets from MS-MPPE-Send-Key are used as the key if the key
801 * data is not present. This seems to be meaning the beginning
802 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
803 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
804 * Anyway, taking the beginning of the keying material from EAP
805 * seems to interoperate with Authenticators.
807 key_len = rx_key_length;
808 os_memcpy(datakey, keydata.encr_key, key_len);
809 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
810 "material data encryption key",
813 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
814 "(key_length=%d)", key_len, rx_key_length);
818 sm->replay_counter_valid = TRUE;
819 os_memcpy(sm->last_replay_counter, key->replay_counter,
820 IEEE8021X_REPLAY_COUNTER_LEN);
822 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
824 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
825 "unicast" : "broadcast",
826 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
828 if (sm->ctx->set_wep_key &&
829 sm->ctx->set_wep_key(sm->ctx->ctx,
830 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
831 key->key_index & IEEE8021X_KEY_INDEX_MASK,
832 datakey, key_len) < 0) {
833 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
836 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
837 sm->unicast_key_received = TRUE;
839 sm->broadcast_key_received = TRUE;
841 if ((sm->unicast_key_received ||
842 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
843 (sm->broadcast_key_received ||
844 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
846 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
848 sm->portValid = TRUE;
849 if (sm->ctx->eapol_done_cb)
850 sm->ctx->eapol_done_cb(sm->ctx->ctx);
853 #endif /* CONFIG_FIPS */
857 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
859 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
860 /* EAP layer processing; no special code is needed, since Supplicant
861 * Backend state machine is waiting for eapNoResp or eapResp to be set
862 * and these are only set in the EAP state machine when the processing
867 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
871 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
873 #ifdef CONFIG_EAP_PROXY
874 if (sm->use_eap_proxy) {
875 /* Get EAP Response from EAP Proxy */
876 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
878 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
879 "response data not available");
883 #endif /* CONFIG_EAP_PROXY */
885 resp = eap_get_eapRespData(sm->eap);
887 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
892 /* Send EAP-Packet from the EAP layer to the Authenticator */
893 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
894 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
897 /* eapRespData is not used anymore, so free it here */
901 sm->dot1xSuppEapolReqIdFramesRx++;
903 sm->dot1xSuppEapolReqFramesRx++;
904 sm->dot1xSuppEapolRespFramesTx++;
905 sm->dot1xSuppEapolFramesTx++;
909 static void eapol_sm_abortSupp(struct eapol_sm *sm)
911 /* release system resources that may have been allocated for the
912 * authentication session */
913 os_free(sm->last_rx_key);
914 sm->last_rx_key = NULL;
915 wpabuf_free(sm->eapReqData);
916 sm->eapReqData = NULL;
917 eap_sm_abort(sm->eap);
918 #ifdef CONFIG_EAP_PROXY
919 eap_proxy_sm_abort(sm->eap_proxy);
920 #endif /* CONFIG_EAP_PROXY */
924 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
926 eapol_sm_step(timeout_ctx);
930 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
934 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
935 sm->force_authorized_update = FALSE;
936 sm->suppPortStatus = Authorized;
937 if (cb && sm->ctx->port_cb)
938 sm->ctx->port_cb(sm->ctx->ctx, 1);
942 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
946 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
947 sm->force_authorized_update = FALSE;
948 sm->suppPortStatus = Unauthorized;
949 if (cb && sm->ctx->port_cb)
950 sm->ctx->port_cb(sm->ctx->ctx, 0);
955 * eapol_sm_step - EAPOL state machine step function
956 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
958 * This function is called to notify the state machine about changed external
959 * variables. It will step through the EAPOL state machines in loop to process
960 * all triggered state changes.
962 void eapol_sm_step(struct eapol_sm *sm)
966 /* In theory, it should be ok to run this in loop until !changed.
967 * However, it is better to use a limit on number of iterations to
968 * allow events (e.g., SIGTERM) to stop the program cleanly if the
969 * state machine were to generate a busy loop. */
970 for (i = 0; i < 100; i++) {
972 SM_STEP_RUN(SUPP_PAE);
974 SM_STEP_RUN(SUPP_BE);
975 #ifdef CONFIG_EAP_PROXY
976 if (sm->use_eap_proxy) {
977 /* Drive the EAP proxy state machine */
978 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
981 #endif /* CONFIG_EAP_PROXY */
982 if (eap_peer_sm_step(sm->eap))
989 /* restart EAPOL state machine step from timeout call in order
990 * to allow other events to be processed. */
991 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
992 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
995 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
996 enum eapol_supp_result result;
997 if (sm->cb_status == EAPOL_CB_SUCCESS)
998 result = EAPOL_SUPP_RESULT_SUCCESS;
999 else if (eap_peer_was_failure_expected(sm->eap))
1000 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
1002 result = EAPOL_SUPP_RESULT_FAILURE;
1003 sm->cb_status = EAPOL_CB_IN_PROGRESS;
1004 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
1009 #ifdef CONFIG_CTRL_IFACE
1010 static const char *eapol_supp_pae_state(int state)
1013 case SUPP_PAE_LOGOFF:
1015 case SUPP_PAE_DISCONNECTED:
1016 return "DISCONNECTED";
1017 case SUPP_PAE_CONNECTING:
1018 return "CONNECTING";
1019 case SUPP_PAE_AUTHENTICATING:
1020 return "AUTHENTICATING";
1023 case SUPP_PAE_AUTHENTICATED:
1024 return "AUTHENTICATED";
1025 case SUPP_PAE_RESTART:
1033 static const char *eapol_supp_be_state(int state)
1036 case SUPP_BE_REQUEST:
1038 case SUPP_BE_RESPONSE:
1040 case SUPP_BE_SUCCESS:
1044 case SUPP_BE_TIMEOUT:
1048 case SUPP_BE_INITIALIZE:
1049 return "INITIALIZE";
1050 case SUPP_BE_RECEIVE:
1058 static const char * eapol_port_status(PortStatus status)
1060 if (status == Authorized)
1061 return "Authorized";
1063 return "Unauthorized";
1065 #endif /* CONFIG_CTRL_IFACE */
1068 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1069 static const char * eapol_port_control(PortControl ctrl)
1074 case ForceUnauthorized:
1075 return "ForceUnauthorized";
1076 case ForceAuthorized:
1077 return "ForceAuthorized";
1082 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1086 * eapol_sm_configure - Set EAPOL variables
1087 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1088 * @heldPeriod: dot1xSuppHeldPeriod
1089 * @authPeriod: dot1xSuppAuthPeriod
1090 * @startPeriod: dot1xSuppStartPeriod
1091 * @maxStart: dot1xSuppMaxStart
1093 * Set configurable EAPOL state machine variables. Each variable can be set to
1094 * the given value or ignored if set to -1 (to set only some of the variables).
1096 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1097 int startPeriod, int maxStart)
1101 if (heldPeriod >= 0)
1102 sm->heldPeriod = heldPeriod;
1103 if (authPeriod >= 0)
1104 sm->authPeriod = authPeriod;
1105 if (startPeriod >= 0)
1106 sm->startPeriod = startPeriod;
1108 sm->maxStart = maxStart;
1113 * eapol_sm_get_method_name - Get EAPOL method name
1114 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1115 * Returns: Static string containing name of current eap method or NULL
1117 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1119 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1120 sm->suppPortStatus != Authorized)
1123 return eap_sm_get_method_name(sm->eap);
1127 #ifdef CONFIG_CTRL_IFACE
1129 * eapol_sm_get_status - Get EAPOL state machine status
1130 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1131 * @buf: Buffer for status information
1132 * @buflen: Maximum buffer length
1133 * @verbose: Whether to include verbose status information
1134 * Returns: Number of bytes written to buf.
1136 * Query EAPOL state machine for status information. This function fills in a
1137 * text area with current status information from the EAPOL state machine. If
1138 * the buffer (buf) is not large enough, status information will be truncated
1139 * to fit the buffer.
1141 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1148 len = os_snprintf(buf, buflen,
1149 "Supplicant PAE state=%s\n"
1150 "suppPortStatus=%s\n",
1151 eapol_supp_pae_state(sm->SUPP_PAE_state),
1152 eapol_port_status(sm->suppPortStatus));
1153 if (os_snprintf_error(buflen, len))
1157 ret = os_snprintf(buf + len, buflen - len,
1163 "Supplicant Backend state=%s\n",
1168 eapol_port_control(sm->portControl),
1169 eapol_supp_be_state(sm->SUPP_BE_state));
1170 if (os_snprintf_error(buflen - len, ret))
1175 #ifdef CONFIG_EAP_PROXY
1176 if (sm->use_eap_proxy)
1177 len += eap_proxy_sm_get_status(sm->eap_proxy,
1178 buf + len, buflen - len,
1181 #endif /* CONFIG_EAP_PROXY */
1182 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1189 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1190 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1191 * @buf: Buffer for MIB information
1192 * @buflen: Maximum buffer length
1193 * Returns: Number of bytes written to buf.
1195 * Query EAPOL state machine for MIB information. This function fills in a
1196 * text area with current MIB information from the EAPOL state machine. If
1197 * the buffer (buf) is not large enough, MIB information will be truncated to
1200 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1207 ret = os_snprintf(buf, buflen,
1208 "dot1xSuppPaeState=%d\n"
1209 "dot1xSuppHeldPeriod=%u\n"
1210 "dot1xSuppAuthPeriod=%u\n"
1211 "dot1xSuppStartPeriod=%u\n"
1212 "dot1xSuppMaxStart=%u\n"
1213 "dot1xSuppSuppControlledPortStatus=%s\n"
1214 "dot1xSuppBackendPaeState=%d\n",
1220 sm->suppPortStatus == Authorized ?
1221 "Authorized" : "Unauthorized",
1224 if (os_snprintf_error(buflen, ret))
1228 ret = os_snprintf(buf + len, buflen - len,
1229 "dot1xSuppEapolFramesRx=%u\n"
1230 "dot1xSuppEapolFramesTx=%u\n"
1231 "dot1xSuppEapolStartFramesTx=%u\n"
1232 "dot1xSuppEapolLogoffFramesTx=%u\n"
1233 "dot1xSuppEapolRespFramesTx=%u\n"
1234 "dot1xSuppEapolReqIdFramesRx=%u\n"
1235 "dot1xSuppEapolReqFramesRx=%u\n"
1236 "dot1xSuppInvalidEapolFramesRx=%u\n"
1237 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1238 "dot1xSuppLastEapolFrameVersion=%u\n"
1239 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1240 sm->dot1xSuppEapolFramesRx,
1241 sm->dot1xSuppEapolFramesTx,
1242 sm->dot1xSuppEapolStartFramesTx,
1243 sm->dot1xSuppEapolLogoffFramesTx,
1244 sm->dot1xSuppEapolRespFramesTx,
1245 sm->dot1xSuppEapolReqIdFramesRx,
1246 sm->dot1xSuppEapolReqFramesRx,
1247 sm->dot1xSuppInvalidEapolFramesRx,
1248 sm->dot1xSuppEapLengthErrorFramesRx,
1249 sm->dot1xSuppLastEapolFrameVersion,
1250 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1252 if (os_snprintf_error(buflen - len, ret))
1258 #endif /* CONFIG_CTRL_IFACE */
1262 * eapol_sm_rx_eapol - Process received EAPOL frames
1263 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1264 * @src: Source MAC address of the EAPOL packet
1265 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1266 * @len: Length of the EAPOL frame
1267 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1270 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1273 const struct ieee802_1x_hdr *hdr;
1274 const struct ieee802_1x_eapol_key *key;
1281 sm->dot1xSuppEapolFramesRx++;
1282 if (len < sizeof(*hdr)) {
1283 sm->dot1xSuppInvalidEapolFramesRx++;
1286 hdr = (const struct ieee802_1x_hdr *) buf;
1287 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1288 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1289 if (hdr->version < EAPOL_VERSION) {
1290 /* TODO: backwards compatibility */
1292 plen = be_to_host16(hdr->length);
1293 if (plen > len - sizeof(*hdr)) {
1294 sm->dot1xSuppEapLengthErrorFramesRx++;
1298 if (sm->conf.wps && sm->conf.workaround &&
1299 plen < len - sizeof(*hdr) &&
1300 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1301 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1302 const struct eap_hdr *ehdr =
1303 (const struct eap_hdr *) (hdr + 1);
1306 elen = be_to_host16(ehdr->length);
1307 if (elen > plen && elen <= len - sizeof(*hdr)) {
1309 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1310 * packets with too short EAPOL header length field
1311 * (14 octets). This is fixed in firmware Ver.1.49.
1312 * As a workaround, fix the EAPOL header based on the
1313 * correct length in the EAP packet.
1315 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1316 "payload length based on EAP header: "
1317 "%d -> %d", (int) plen, elen);
1321 #endif /* CONFIG_WPS */
1322 data_len = plen + sizeof(*hdr);
1324 switch (hdr->type) {
1325 case IEEE802_1X_TYPE_EAP_PACKET:
1326 if (sm->conf.workaround) {
1328 * An AP has been reported to send out EAP message with
1329 * undocumented code 10 at some point near the
1330 * completion of EAP authentication. This can result in
1331 * issues with the unexpected EAP message triggering
1332 * restart of EAPOL authentication. Avoid this by
1333 * skipping the message without advancing the state
1336 const struct eap_hdr *ehdr =
1337 (const struct eap_hdr *) (hdr + 1);
1338 if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1339 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1344 if (sm->cached_pmk) {
1345 /* Trying to use PMKSA caching, but Authenticator did
1346 * not seem to have a matching entry. Need to restart
1347 * EAPOL state machines.
1349 eapol_sm_abort_cached(sm);
1351 wpabuf_free(sm->eapReqData);
1352 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1353 if (sm->eapReqData) {
1354 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1356 sm->eapolEap = TRUE;
1357 #ifdef CONFIG_EAP_PROXY
1358 if (sm->use_eap_proxy) {
1359 eap_proxy_packet_update(
1361 wpabuf_mhead_u8(sm->eapReqData),
1362 wpabuf_len(sm->eapReqData));
1363 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1366 #endif /* CONFIG_EAP_PROXY */
1370 case IEEE802_1X_TYPE_EAPOL_KEY:
1371 if (plen < sizeof(*key)) {
1372 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1376 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1377 if (key->type == EAPOL_KEY_TYPE_WPA ||
1378 key->type == EAPOL_KEY_TYPE_RSN) {
1379 /* WPA Supplicant takes care of this frame. */
1380 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1381 "frame in EAPOL state machines");
1385 if (key->type != EAPOL_KEY_TYPE_RC4) {
1386 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1387 "EAPOL-Key type %d", key->type);
1390 os_free(sm->last_rx_key);
1391 sm->last_rx_key = os_malloc(data_len);
1392 if (sm->last_rx_key) {
1393 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1395 os_memcpy(sm->last_rx_key, buf, data_len);
1396 sm->last_rx_key_len = data_len;
1401 #ifdef CONFIG_MACSEC
1402 case IEEE802_1X_TYPE_EAPOL_MKA:
1403 wpa_printf(MSG_EXCESSIVE,
1404 "EAPOL type %d will be handled by MKA",
1407 #endif /* CONFIG_MACSEC */
1409 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1411 sm->dot1xSuppInvalidEapolFramesRx++;
1420 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1421 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1423 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1424 * component, e.g., WPA. This will update the statistics.
1426 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1429 sm->dot1xSuppEapolFramesTx++;
1434 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1435 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1436 * @enabled: New portEnabled value
1438 * Notify EAPOL state machine about new portEnabled value.
1440 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1444 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1445 "portEnabled=%d", enabled);
1446 if (sm->portEnabled != enabled)
1447 sm->force_authorized_update = TRUE;
1448 sm->portEnabled = enabled;
1454 * eapol_sm_notify_portValid - Notification about portValid change
1455 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1456 * @valid: New portValid value
1458 * Notify EAPOL state machine about new portValid value.
1460 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1464 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1465 "portValid=%d", valid);
1466 sm->portValid = valid;
1472 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1473 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1474 * @success: %TRUE = set success, %FALSE = clear success
1476 * Notify the EAPOL state machine that external event has forced EAP state to
1477 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1479 * This function is called to update EAP state when WPA-PSK key handshake has
1480 * been completed successfully since WPA-PSK does not use EAP state machine.
1482 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1486 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1487 "EAP success=%d", success);
1488 sm->eapSuccess = success;
1489 sm->altAccept = success;
1491 eap_notify_success(sm->eap);
1497 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1498 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1499 * @fail: %TRUE = set failure, %FALSE = clear failure
1501 * Notify EAPOL state machine that external event has forced EAP state to
1502 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1504 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1508 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1509 "EAP fail=%d", fail);
1511 sm->altReject = fail;
1517 * eapol_sm_notify_config - Notification of EAPOL configuration change
1518 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1519 * @config: Pointer to current network EAP configuration
1520 * @conf: Pointer to EAPOL configuration data
1522 * Notify EAPOL state machine that configuration has changed. config will be
1523 * stored as a backpointer to network configuration. This can be %NULL to clear
1524 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1525 * data. If conf is %NULL, this part of the configuration change will be
1528 void eapol_sm_notify_config(struct eapol_sm *sm,
1529 struct eap_peer_config *config,
1530 const struct eapol_config *conf)
1535 sm->config = config;
1536 #ifdef CONFIG_EAP_PROXY
1537 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1538 #endif /* CONFIG_EAP_PROXY */
1543 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1544 sm->conf.required_keys = conf->required_keys;
1545 sm->conf.fast_reauth = conf->fast_reauth;
1546 sm->conf.workaround = conf->workaround;
1547 sm->conf.wps = conf->wps;
1548 #ifdef CONFIG_EAP_PROXY
1549 if (sm->use_eap_proxy) {
1550 /* Using EAP Proxy, so skip EAP state machine update */
1553 #endif /* CONFIG_EAP_PROXY */
1555 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1556 eap_set_workaround(sm->eap, conf->workaround);
1557 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1558 eap_set_external_sim(sm->eap, conf->external_sim);
1564 * eapol_sm_get_key - Get master session key (MSK) from EAP
1565 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1566 * @key: Pointer for key buffer
1567 * @len: Number of bytes to copy to key
1568 * Returns: 0 on success (len of key available), maximum available key len
1569 * (>0) if key is available but it is shorter than len, or -1 on failure.
1571 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1572 * is available only after a successful authentication.
1574 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1579 #ifdef CONFIG_EAP_PROXY
1580 if (sm && sm->use_eap_proxy) {
1581 /* Get key from EAP proxy */
1582 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1583 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1586 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1587 if (eap_key == NULL) {
1588 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1594 #endif /* CONFIG_EAP_PROXY */
1595 if (sm == NULL || !eap_key_available(sm->eap)) {
1596 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1599 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1600 if (eap_key == NULL) {
1601 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1604 #ifdef CONFIG_EAP_PROXY
1606 #endif /* CONFIG_EAP_PROXY */
1607 if (len > eap_len) {
1608 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1609 "available (len=%lu)",
1610 (unsigned long) len, (unsigned long) eap_len);
1613 os_memcpy(key, eap_key, len);
1614 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1615 (unsigned long) len);
1621 * eapol_sm_get_session_id - Get EAP Session-Id
1622 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1623 * @len: Pointer to variable that will be set to number of bytes in the session
1624 * Returns: Pointer to the EAP Session-Id or %NULL on failure
1626 * The Session-Id is available only after a successful authentication.
1628 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
1630 if (sm == NULL || !eap_key_available(sm->eap)) {
1631 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
1634 return eap_get_eapSessionId(sm->eap, len);
1639 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1640 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1641 * @logoff: Whether command was logoff
1643 * Notify EAPOL state machines that user requested logon/logoff.
1645 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1648 sm->userLogoff = logoff;
1650 /* If there is a delayed txStart queued, start now. */
1659 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1660 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1662 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1663 * to move EAPOL and EAP state machines into authenticated/successful state.
1665 void eapol_sm_notify_cached(struct eapol_sm *sm)
1669 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1670 sm->eapSuccess = TRUE;
1671 eap_notify_success(sm->eap);
1677 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1678 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1680 * Notify EAPOL state machines if PMKSA caching is used.
1682 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm)
1686 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1687 sm->cached_pmk = TRUE;
1691 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1693 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1694 "doing full EAP authentication");
1697 sm->cached_pmk = FALSE;
1698 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1699 eapol_sm_set_port_unauthorized(sm);
1701 /* Make sure we do not start sending EAPOL-Start frames first, but
1702 * instead move to RESTART state to start EAPOL authentication. */
1704 eapol_enable_timer_tick(sm);
1706 if (sm->ctx->aborted_cached)
1707 sm->ctx->aborted_cached(sm->ctx->ctx);
1712 * eapol_sm_register_scard_ctx - Notification of smart card context
1713 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1714 * @ctx: Context data for smart card operations
1716 * Notify EAPOL state machines of context data for smart card operations. This
1717 * context data will be used as a parameter for scard_*() functions.
1719 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1722 sm->ctx->scard_ctx = ctx;
1723 eap_register_scard_ctx(sm->eap, ctx);
1729 * eapol_sm_notify_portControl - Notification of portControl changes
1730 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1731 * @portControl: New value for portControl variable
1733 * Notify EAPOL state machines that portControl variable has changed.
1735 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1739 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1740 "portControl=%s", eapol_port_control(portControl));
1741 sm->portControl = portControl;
1747 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1748 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1750 * Notify EAPOL state machines that a monitor was attached to the control
1751 * interface to trigger re-sending of pending requests for user input.
1753 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1757 eap_sm_notify_ctrl_attached(sm->eap);
1762 * eapol_sm_notify_ctrl_response - Notification of received user input
1763 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1765 * Notify EAPOL state machines that a control response, i.e., user
1766 * input, was received in order to trigger retrying of a pending EAP request.
1768 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1772 if (sm->eapReqData && !sm->eapReq) {
1773 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1774 "input) notification - retrying pending EAP "
1776 sm->eapolEap = TRUE;
1784 * eapol_sm_request_reauth - Request reauthentication
1785 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1787 * This function can be used to request EAPOL reauthentication, e.g., when the
1788 * current PMKSA entry is nearing expiration.
1790 void eapol_sm_request_reauth(struct eapol_sm *sm)
1792 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1794 eapol_sm_txStart(sm);
1799 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1800 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1801 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1802 * machine loop (eapol_sm_step())
1804 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1805 * successful authentication. This is used to recover from dropped EAP-Success
1808 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1812 eap_notify_lower_layer_success(sm->eap);
1819 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1820 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1822 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1825 eap_invalidate_cached_session(sm->eap);
1829 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1831 struct eapol_sm *sm = ctx;
1832 return sm ? sm->config : NULL;
1836 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1838 struct eapol_sm *sm = ctx;
1839 if (sm == NULL || sm->eapReqData == NULL)
1842 return sm->eapReqData;
1846 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1848 struct eapol_sm *sm = ctx;
1852 case EAPOL_eapSuccess:
1853 return sm->eapSuccess;
1854 case EAPOL_eapRestart:
1855 return sm->eapRestart;
1860 case EAPOL_eapNoResp:
1861 return sm->eapNoResp;
1864 case EAPOL_portEnabled:
1865 return sm->portEnabled;
1866 case EAPOL_altAccept:
1867 return sm->altAccept;
1868 case EAPOL_altReject:
1869 return sm->altReject;
1870 case EAPOL_eapTriggerStart:
1871 return sm->eapTriggerStart;
1877 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1880 struct eapol_sm *sm = ctx;
1884 case EAPOL_eapSuccess:
1885 sm->eapSuccess = value;
1887 case EAPOL_eapRestart:
1888 sm->eapRestart = value;
1891 sm->eapFail = value;
1894 sm->eapResp = value;
1896 case EAPOL_eapNoResp:
1897 sm->eapNoResp = value;
1902 case EAPOL_portEnabled:
1903 sm->portEnabled = value;
1905 case EAPOL_altAccept:
1906 sm->altAccept = value;
1908 case EAPOL_altReject:
1909 sm->altReject = value;
1911 case EAPOL_eapTriggerStart:
1912 sm->eapTriggerStart = value;
1918 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1920 struct eapol_sm *sm = ctx;
1924 case EAPOL_idleWhile:
1925 return sm->idleWhile;
1931 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1934 struct eapol_sm *sm = ctx;
1938 case EAPOL_idleWhile:
1939 sm->idleWhile = value;
1940 if (sm->idleWhile > 0)
1941 eapol_enable_timer_tick(sm);
1947 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1949 #ifndef CONFIG_NO_CONFIG_BLOBS
1950 struct eapol_sm *sm = ctx;
1951 if (sm && sm->ctx && sm->ctx->set_config_blob)
1952 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1953 #endif /* CONFIG_NO_CONFIG_BLOBS */
1957 static const struct wpa_config_blob *
1958 eapol_sm_get_config_blob(void *ctx, const char *name)
1960 #ifndef CONFIG_NO_CONFIG_BLOBS
1961 struct eapol_sm *sm = ctx;
1962 if (sm && sm->ctx && sm->ctx->get_config_blob)
1963 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1966 #else /* CONFIG_NO_CONFIG_BLOBS */
1968 #endif /* CONFIG_NO_CONFIG_BLOBS */
1972 static void eapol_sm_notify_pending(void *ctx)
1974 struct eapol_sm *sm = ctx;
1977 if (sm->eapReqData && !sm->eapReq) {
1978 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1979 "state machine - retrying pending EAP Request");
1980 sm->eapolEap = TRUE;
1987 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1988 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1991 struct eapol_sm *sm = ctx;
1992 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1993 if (sm->ctx->eap_param_needed)
1994 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1996 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1997 #define eapol_sm_eap_param_needed NULL
1998 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
2000 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
2001 const char *altsubject[],
2002 int num_altsubject, const char *cert_hash,
2003 const struct wpabuf *cert)
2005 struct eapol_sm *sm = ctx;
2006 if (sm->ctx->cert_cb)
2007 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, altsubject,
2008 num_altsubject, cert_hash, cert);
2012 static void eapol_sm_notify_status(void *ctx, const char *status,
2013 const char *parameter)
2015 struct eapol_sm *sm = ctx;
2017 if (sm->ctx->status_cb)
2018 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
2022 static void eapol_sm_notify_eap_error(void *ctx, int error_code)
2024 struct eapol_sm *sm = ctx;
2026 if (sm->ctx->eap_error_cb)
2027 sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
2031 #ifdef CONFIG_EAP_PROXY
2033 static void eapol_sm_eap_proxy_cb(void *ctx)
2035 struct eapol_sm *sm = ctx;
2037 if (sm->ctx->eap_proxy_cb)
2038 sm->ctx->eap_proxy_cb(sm->ctx->ctx);
2043 eapol_sm_eap_proxy_notify_sim_status(void *ctx,
2044 enum eap_proxy_sim_state sim_state)
2046 struct eapol_sm *sm = ctx;
2048 if (sm->ctx->eap_proxy_notify_sim_status)
2049 sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state);
2052 #endif /* CONFIG_EAP_PROXY */
2055 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
2057 struct eapol_sm *sm = ctx;
2059 if (sm->ctx->set_anon_id)
2060 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
2064 static const struct eapol_callbacks eapol_cb =
2066 eapol_sm_get_config,
2071 eapol_sm_get_eapReqData,
2072 eapol_sm_set_config_blob,
2073 eapol_sm_get_config_blob,
2074 eapol_sm_notify_pending,
2075 eapol_sm_eap_param_needed,
2076 eapol_sm_notify_cert,
2077 eapol_sm_notify_status,
2078 eapol_sm_notify_eap_error,
2079 #ifdef CONFIG_EAP_PROXY
2080 eapol_sm_eap_proxy_cb,
2081 eapol_sm_eap_proxy_notify_sim_status,
2082 eapol_sm_get_eap_proxy_imsi,
2083 #endif /* CONFIG_EAP_PROXY */
2084 eapol_sm_set_anon_id
2089 * eapol_sm_init - Initialize EAPOL state machine
2090 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2091 * and EAPOL state machine will free it in eapol_sm_deinit()
2092 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2094 * Allocate and initialize an EAPOL state machine.
2096 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
2098 struct eapol_sm *sm;
2099 struct eap_config conf;
2100 sm = os_zalloc(sizeof(*sm));
2105 sm->portControl = Auto;
2107 /* Supplicant PAE state machine */
2108 sm->heldPeriod = 60;
2109 sm->startPeriod = 30;
2112 /* Supplicant Backend state machine */
2113 sm->authPeriod = 30;
2115 os_memset(&conf, 0, sizeof(conf));
2116 conf.opensc_engine_path = ctx->opensc_engine_path;
2117 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2118 conf.pkcs11_module_path = ctx->pkcs11_module_path;
2119 conf.openssl_ciphers = ctx->openssl_ciphers;
2120 conf.wps = ctx->wps;
2121 conf.cert_in_cb = ctx->cert_in_cb;
2123 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2124 if (sm->eap == NULL) {
2129 #ifdef CONFIG_EAP_PROXY
2130 sm->use_eap_proxy = FALSE;
2131 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2132 if (sm->eap_proxy == NULL) {
2133 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2135 #endif /* CONFIG_EAP_PROXY */
2137 /* Initialize EAPOL state machines */
2138 sm->force_authorized_update = TRUE;
2139 sm->initialize = TRUE;
2141 sm->initialize = FALSE;
2144 sm->timer_tick_enabled = 1;
2145 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2152 * eapol_sm_deinit - Deinitialize EAPOL state machine
2153 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2155 * Deinitialize and free EAPOL state machine.
2157 void eapol_sm_deinit(struct eapol_sm *sm)
2161 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2162 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2163 eap_peer_sm_deinit(sm->eap);
2164 #ifdef CONFIG_EAP_PROXY
2165 eap_proxy_deinit(sm->eap_proxy);
2166 #endif /* CONFIG_EAP_PROXY */
2167 os_free(sm->last_rx_key);
2168 wpabuf_free(sm->eapReqData);
2174 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2175 struct ext_password_data *ext)
2178 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2182 int eapol_sm_failed(struct eapol_sm *sm)
2186 return !sm->eapSuccess && sm->eapFail;
2190 #ifdef CONFIG_EAP_PROXY
2191 int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len)
2193 struct eapol_sm *sm = ctx;
2195 if (sm->eap_proxy == NULL)
2197 return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len);
2199 #endif /* CONFIG_EAP_PROXY */
2202 void eapol_sm_erp_flush(struct eapol_sm *sm)
2205 eap_peer_erp_free_keys(sm->eap);
2209 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
2214 return eap_peer_build_erp_reauth_start(sm->eap, 0);
2215 #else /* CONFIG_ERP */
2217 #endif /* CONFIG_ERP */
2221 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
2227 eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
2228 #endif /* CONFIG_ERP */
2232 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
2237 return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
2238 #else /* CONFIG_ERP */
2240 #endif /* CONFIG_ERP */
2244 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
2245 const u8 **username, size_t *username_len,
2246 const u8 **realm, size_t *realm_len,
2247 u16 *erp_next_seq_num, const u8 **rrk,
2253 return eap_peer_get_erp_info(sm->eap, config, username, username_len,
2254 realm, realm_len, erp_next_seq_num, rrk,
2256 #else /* CONFIG_ERP */
2258 #endif /* CONFIG_ERP */