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 "eapol_supp_sm.h"
21 #define STATE_MACHINE_DATA struct eapol_sm
22 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
25 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
28 * struct eapol_sm - Internal data for EAPOL state machines
32 unsigned int authWhile;
33 unsigned int heldWhile;
34 unsigned int startWhen;
35 unsigned int idleWhile; /* for EAP state machine */
36 int timer_tick_enabled;
38 /* Global variables */
45 PortControl portControl;
47 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
55 /* Supplicant PAE state machine */
58 SUPP_PAE_DISCONNECTED = 1,
60 SUPP_PAE_CONNECTING = 3,
61 SUPP_PAE_AUTHENTICATING = 4,
62 SUPP_PAE_AUTHENTICATED = 5,
66 SUPP_PAE_S_FORCE_AUTH = 9,
67 SUPP_PAE_S_FORCE_UNAUTH = 10
68 } SUPP_PAE_state; /* dot1xSuppPaeState */
72 unsigned int startCount;
74 PortControl sPortMode;
76 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
77 unsigned int startPeriod; /* dot1xSuppStartPeriod */
78 unsigned int maxStart; /* dot1xSuppMaxStart */
80 /* Key Receive state machine */
83 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
88 /* Supplicant Backend state machine */
91 SUPP_BE_INITIALIZE = 1,
99 } SUPP_BE_state; /* dot1xSuppBackendPaeState */
105 unsigned int authPeriod; /* dot1xSuppAuthPeriod */
108 unsigned int dot1xSuppEapolFramesRx;
109 unsigned int dot1xSuppEapolFramesTx;
110 unsigned int dot1xSuppEapolStartFramesTx;
111 unsigned int dot1xSuppEapolLogoffFramesTx;
112 unsigned int dot1xSuppEapolRespFramesTx;
113 unsigned int dot1xSuppEapolReqIdFramesRx;
114 unsigned int dot1xSuppEapolReqFramesRx;
115 unsigned int dot1xSuppInvalidEapolFramesRx;
116 unsigned int dot1xSuppEapLengthErrorFramesRx;
117 unsigned int dot1xSuppLastEapolFrameVersion;
118 unsigned char dot1xSuppLastEapolFrameSource[6];
120 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
123 struct eap_peer_config *config;
126 size_t last_rx_key_len;
127 struct wpabuf *eapReqData; /* for EAP */
128 Boolean altAccept; /* for EAP */
129 Boolean altReject; /* for EAP */
130 Boolean replay_counter_valid;
131 u8 last_replay_counter[16];
132 struct eapol_config conf;
133 struct eapol_ctx *ctx;
134 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
138 Boolean unicast_key_received, broadcast_key_received;
142 static void eapol_sm_txLogoff(struct eapol_sm *sm);
143 static void eapol_sm_txStart(struct eapol_sm *sm);
144 static void eapol_sm_processKey(struct eapol_sm *sm);
145 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
146 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
147 static void eapol_sm_abortSupp(struct eapol_sm *sm);
148 static void eapol_sm_abort_cached(struct eapol_sm *sm);
149 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
150 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
151 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
154 /* Port Timers state machine - implemented as a function that will be called
155 * once a second as a registered event loop timeout */
156 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
158 struct eapol_sm *sm = timeout_ctx;
160 if (sm->authWhile > 0) {
162 if (sm->authWhile == 0)
163 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
165 if (sm->heldWhile > 0) {
167 if (sm->heldWhile == 0)
168 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
170 if (sm->startWhen > 0) {
172 if (sm->startWhen == 0)
173 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
175 if (sm->idleWhile > 0) {
177 if (sm->idleWhile == 0)
178 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
181 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
182 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
185 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
186 sm->timer_tick_enabled = 0;
192 static void eapol_enable_timer_tick(struct eapol_sm *sm)
194 if (sm->timer_tick_enabled)
196 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
197 sm->timer_tick_enabled = 1;
198 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
199 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
203 SM_STATE(SUPP_PAE, LOGOFF)
205 SM_ENTRY(SUPP_PAE, LOGOFF);
206 eapol_sm_txLogoff(sm);
207 sm->logoffSent = TRUE;
208 sm->suppPortStatus = Unauthorized;
209 eapol_sm_set_port_unauthorized(sm);
213 SM_STATE(SUPP_PAE, DISCONNECTED)
215 SM_ENTRY(SUPP_PAE, DISCONNECTED);
216 sm->sPortMode = Auto;
218 sm->logoffSent = FALSE;
219 sm->suppPortStatus = Unauthorized;
220 eapol_sm_set_port_unauthorized(sm);
221 sm->suppAbort = TRUE;
223 sm->unicast_key_received = FALSE;
224 sm->broadcast_key_received = FALSE;
227 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
228 * allows the timer tick to be stopped more quickly when the port is
229 * not enabled. Since this variable is used only within HELD state,
230 * clearing it on initialization does not change actual state machine
237 SM_STATE(SUPP_PAE, CONNECTING)
239 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
240 SM_ENTRY(SUPP_PAE, CONNECTING);
242 sm->startWhen = sm->startPeriod;
246 * Do not send EAPOL-Start immediately since in most cases,
247 * Authenticator is going to start authentication immediately
248 * after association and an extra EAPOL-Start is just going to
249 * delay authentication. Use a short timeout to send the first
250 * EAPOL-Start if Authenticator does not start authentication.
253 /* Reduce latency on starting WPS negotiation. */
255 #else /* CONFIG_WPS */
257 #endif /* CONFIG_WPS */
259 eapol_enable_timer_tick(sm);
260 sm->eapolEap = FALSE;
262 eapol_sm_txStart(sm);
266 SM_STATE(SUPP_PAE, AUTHENTICATING)
268 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
270 sm->suppSuccess = FALSE;
271 sm->suppFail = FALSE;
272 sm->suppTimeout = FALSE;
275 sm->suppStart = TRUE;
279 SM_STATE(SUPP_PAE, HELD)
281 SM_ENTRY(SUPP_PAE, HELD);
282 sm->heldWhile = sm->heldPeriod;
283 eapol_enable_timer_tick(sm);
284 sm->suppPortStatus = Unauthorized;
285 eapol_sm_set_port_unauthorized(sm);
286 sm->cb_status = EAPOL_CB_FAILURE;
290 SM_STATE(SUPP_PAE, AUTHENTICATED)
292 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
293 sm->suppPortStatus = Authorized;
294 eapol_sm_set_port_authorized(sm);
295 sm->cb_status = EAPOL_CB_SUCCESS;
299 SM_STATE(SUPP_PAE, RESTART)
301 SM_ENTRY(SUPP_PAE, RESTART);
302 sm->eapRestart = TRUE;
306 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
308 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
309 sm->suppPortStatus = Authorized;
310 eapol_sm_set_port_authorized(sm);
311 sm->sPortMode = ForceAuthorized;
315 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
317 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
318 sm->suppPortStatus = Unauthorized;
319 eapol_sm_set_port_unauthorized(sm);
320 sm->sPortMode = ForceUnauthorized;
321 eapol_sm_txLogoff(sm);
327 if ((sm->userLogoff && !sm->logoffSent) &&
328 !(sm->initialize || !sm->portEnabled))
329 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
330 else if (((sm->portControl == Auto) &&
331 (sm->sPortMode != sm->portControl)) ||
332 sm->initialize || !sm->portEnabled)
333 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
334 else if ((sm->portControl == ForceAuthorized) &&
335 (sm->sPortMode != sm->portControl) &&
336 !(sm->initialize || !sm->portEnabled))
337 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
338 else if ((sm->portControl == ForceUnauthorized) &&
339 (sm->sPortMode != sm->portControl) &&
340 !(sm->initialize || !sm->portEnabled))
341 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
342 else switch (sm->SUPP_PAE_state) {
343 case SUPP_PAE_UNKNOWN:
345 case SUPP_PAE_LOGOFF:
347 SM_ENTER(SUPP_PAE, DISCONNECTED);
349 case SUPP_PAE_DISCONNECTED:
350 SM_ENTER(SUPP_PAE, CONNECTING);
352 case SUPP_PAE_CONNECTING:
353 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
354 SM_ENTER(SUPP_PAE, CONNECTING);
355 else if (sm->startWhen == 0 &&
356 sm->startCount >= sm->maxStart &&
358 SM_ENTER(SUPP_PAE, AUTHENTICATED);
359 else if (sm->eapSuccess || sm->eapFail)
360 SM_ENTER(SUPP_PAE, AUTHENTICATING);
361 else if (sm->eapolEap)
362 SM_ENTER(SUPP_PAE, RESTART);
363 else if (sm->startWhen == 0 &&
364 sm->startCount >= sm->maxStart &&
366 SM_ENTER(SUPP_PAE, HELD);
368 case SUPP_PAE_AUTHENTICATING:
369 if (sm->eapSuccess && !sm->portValid &&
370 sm->conf.accept_802_1x_keys &&
371 sm->conf.required_keys == 0) {
372 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
373 "plaintext connection; no EAPOL-Key frames "
375 sm->portValid = TRUE;
376 if (sm->ctx->eapol_done_cb)
377 sm->ctx->eapol_done_cb(sm->ctx->ctx);
379 if (sm->eapSuccess && sm->portValid)
380 SM_ENTER(SUPP_PAE, AUTHENTICATED);
381 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
382 SM_ENTER(SUPP_PAE, HELD);
383 else if (sm->suppTimeout)
384 SM_ENTER(SUPP_PAE, CONNECTING);
387 if (sm->heldWhile == 0)
388 SM_ENTER(SUPP_PAE, CONNECTING);
389 else if (sm->eapolEap)
390 SM_ENTER(SUPP_PAE, RESTART);
392 case SUPP_PAE_AUTHENTICATED:
393 if (sm->eapolEap && sm->portValid)
394 SM_ENTER(SUPP_PAE, RESTART);
395 else if (!sm->portValid)
396 SM_ENTER(SUPP_PAE, DISCONNECTED);
398 case SUPP_PAE_RESTART:
400 SM_ENTER(SUPP_PAE, AUTHENTICATING);
402 case SUPP_PAE_S_FORCE_AUTH:
404 case SUPP_PAE_S_FORCE_UNAUTH:
410 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
412 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
416 SM_STATE(KEY_RX, KEY_RECEIVE)
418 SM_ENTRY(KEY_RX, KEY_RECEIVE);
419 eapol_sm_processKey(sm);
426 if (sm->initialize || !sm->portEnabled)
427 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
428 switch (sm->KEY_RX_state) {
431 case KEY_RX_NO_KEY_RECEIVE:
433 SM_ENTER(KEY_RX, KEY_RECEIVE);
435 case KEY_RX_KEY_RECEIVE:
437 SM_ENTER(KEY_RX, KEY_RECEIVE);
443 SM_STATE(SUPP_BE, REQUEST)
445 SM_ENTRY(SUPP_BE, REQUEST);
448 eapol_sm_getSuppRsp(sm);
452 SM_STATE(SUPP_BE, RESPONSE)
454 SM_ENTRY(SUPP_BE, RESPONSE);
455 eapol_sm_txSuppRsp(sm);
460 SM_STATE(SUPP_BE, SUCCESS)
462 SM_ENTRY(SUPP_BE, SUCCESS);
464 sm->suppSuccess = TRUE;
466 if (eap_key_available(sm->eap)) {
467 /* New key received - clear IEEE 802.1X EAPOL-Key replay
469 sm->replay_counter_valid = FALSE;
474 SM_STATE(SUPP_BE, FAIL)
476 SM_ENTRY(SUPP_BE, FAIL);
481 SM_STATE(SUPP_BE, TIMEOUT)
483 SM_ENTRY(SUPP_BE, TIMEOUT);
484 sm->suppTimeout = TRUE;
488 SM_STATE(SUPP_BE, IDLE)
490 SM_ENTRY(SUPP_BE, IDLE);
491 sm->suppStart = FALSE;
492 sm->initial_req = TRUE;
496 SM_STATE(SUPP_BE, INITIALIZE)
498 SM_ENTRY(SUPP_BE, INITIALIZE);
499 eapol_sm_abortSupp(sm);
500 sm->suppAbort = FALSE;
503 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
504 * allows the timer tick to be stopped more quickly when the port is
505 * not enabled. Since this variable is used only within RECEIVE state,
506 * clearing it on initialization does not change actual state machine
513 SM_STATE(SUPP_BE, RECEIVE)
515 SM_ENTRY(SUPP_BE, RECEIVE);
516 sm->authWhile = sm->authPeriod;
517 eapol_enable_timer_tick(sm);
518 sm->eapolEap = FALSE;
519 sm->eapNoResp = FALSE;
520 sm->initial_req = FALSE;
526 if (sm->initialize || sm->suppAbort)
527 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
528 else switch (sm->SUPP_BE_state) {
529 case SUPP_BE_UNKNOWN:
531 case SUPP_BE_REQUEST:
533 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
534 * and SUCCESS based on eapFail and eapSuccess, respectively.
535 * However, IEEE Std 802.1X-2004 is also specifying that
536 * eapNoResp should be set in conjunction with eapSuccess and
537 * eapFail which would mean that more than one of the
538 * transitions here would be activated at the same time.
539 * Skipping RESPONSE and/or RECEIVE states in these cases can
540 * cause problems and the direct transitions to do not seem
541 * correct. Because of this, the conditions for these
542 * transitions are verified only after eapNoResp. They are
543 * unlikely to be used since eapNoResp should always be set if
544 * either of eapSuccess or eapFail is set.
546 if (sm->eapResp && sm->eapNoResp) {
547 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
548 "eapResp and eapNoResp set?!");
551 SM_ENTER(SUPP_BE, RESPONSE);
552 else if (sm->eapNoResp)
553 SM_ENTER(SUPP_BE, RECEIVE);
554 else if (sm->eapFail)
555 SM_ENTER(SUPP_BE, FAIL);
556 else if (sm->eapSuccess)
557 SM_ENTER(SUPP_BE, SUCCESS);
559 case SUPP_BE_RESPONSE:
560 SM_ENTER(SUPP_BE, RECEIVE);
562 case SUPP_BE_SUCCESS:
563 SM_ENTER(SUPP_BE, IDLE);
566 SM_ENTER(SUPP_BE, IDLE);
568 case SUPP_BE_TIMEOUT:
569 SM_ENTER(SUPP_BE, IDLE);
572 if (sm->eapFail && sm->suppStart)
573 SM_ENTER(SUPP_BE, FAIL);
574 else if (sm->eapolEap && sm->suppStart)
575 SM_ENTER(SUPP_BE, REQUEST);
576 else if (sm->eapSuccess && sm->suppStart)
577 SM_ENTER(SUPP_BE, SUCCESS);
579 case SUPP_BE_INITIALIZE:
580 SM_ENTER(SUPP_BE, IDLE);
582 case SUPP_BE_RECEIVE:
584 SM_ENTER(SUPP_BE, REQUEST);
585 else if (sm->eapFail)
586 SM_ENTER(SUPP_BE, FAIL);
587 else if (sm->authWhile == 0)
588 SM_ENTER(SUPP_BE, TIMEOUT);
589 else if (sm->eapSuccess)
590 SM_ENTER(SUPP_BE, SUCCESS);
596 static void eapol_sm_txLogoff(struct eapol_sm *sm)
598 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
599 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
600 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
601 sm->dot1xSuppEapolLogoffFramesTx++;
602 sm->dot1xSuppEapolFramesTx++;
606 static void eapol_sm_txStart(struct eapol_sm *sm)
608 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
609 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
610 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
611 sm->dot1xSuppEapolStartFramesTx++;
612 sm->dot1xSuppEapolFramesTx++;
616 #define IEEE8021X_ENCR_KEY_LEN 32
617 #define IEEE8021X_SIGN_KEY_LEN 32
619 struct eap_key_data {
620 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
621 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
625 static void eapol_sm_processKey(struct eapol_sm *sm)
628 struct ieee802_1x_hdr *hdr;
629 struct ieee802_1x_eapol_key *key;
630 struct eap_key_data keydata;
631 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
632 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
633 int key_len, res, sign_key_len, encr_key_len;
637 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
638 if (sm->last_rx_key == NULL)
641 if (!sm->conf.accept_802_1x_keys) {
642 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
643 " even though this was not accepted - "
644 "ignoring this packet");
648 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
650 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
651 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
652 plen = be_to_host16(hdr->length);
653 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
654 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
657 rx_key_length = WPA_GET_BE16(key->key_length);
658 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
659 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
660 hdr->version, hdr->type, be_to_host16(hdr->length),
661 key->type, rx_key_length, key->key_index);
663 eapol_sm_notify_lower_layer_success(sm, 1);
664 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
665 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
666 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
668 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
669 "decrypting EAPOL-Key keys");
673 /* LEAP derives only 16 bytes of keying material. */
674 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
676 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
677 "master key for decrypting EAPOL-Key keys");
682 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
684 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
685 "data for decrypting EAPOL-Key keys (res=%d)", res);
689 /* The key replay_counter must increase when same master key */
690 if (sm->replay_counter_valid &&
691 os_memcmp(sm->last_replay_counter, key->replay_counter,
692 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
693 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
694 "not increase - ignoring key");
695 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
696 sm->last_replay_counter,
697 IEEE8021X_REPLAY_COUNTER_LEN);
698 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
699 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
703 /* Verify key signature (HMAC-MD5) */
704 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
705 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
706 hmac_md5(keydata.sign_key, sign_key_len,
707 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
709 if (os_memcmp(orig_key_sign, key->key_signature,
710 IEEE8021X_KEY_SIGN_LEN) != 0) {
711 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
713 os_memcpy(key->key_signature, orig_key_sign,
714 IEEE8021X_KEY_SIGN_LEN);
717 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
719 key_len = plen - sizeof(*key);
720 if (key_len > 32 || rx_key_length > 32) {
721 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
722 key_len ? key_len : rx_key_length);
725 if (key_len == rx_key_length) {
726 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
727 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
729 os_memcpy(datakey, key + 1, key_len);
730 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
732 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
734 } else if (key_len == 0) {
736 * IEEE 802.1X-2004 specifies that least significant Key Length
737 * octets from MS-MPPE-Send-Key are used as the key if the key
738 * data is not present. This seems to be meaning the beginning
739 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
740 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
741 * Anyway, taking the beginning of the keying material from EAP
742 * seems to interoperate with Authenticators.
744 key_len = rx_key_length;
745 os_memcpy(datakey, keydata.encr_key, key_len);
746 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
747 "material data encryption key",
750 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
751 "(key_length=%d)", key_len, rx_key_length);
755 sm->replay_counter_valid = TRUE;
756 os_memcpy(sm->last_replay_counter, key->replay_counter,
757 IEEE8021X_REPLAY_COUNTER_LEN);
759 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
761 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
762 "unicast" : "broadcast",
763 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
765 if (sm->ctx->set_wep_key &&
766 sm->ctx->set_wep_key(sm->ctx->ctx,
767 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
768 key->key_index & IEEE8021X_KEY_INDEX_MASK,
769 datakey, key_len) < 0) {
770 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
773 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
774 sm->unicast_key_received = TRUE;
776 sm->broadcast_key_received = TRUE;
778 if ((sm->unicast_key_received ||
779 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
780 (sm->broadcast_key_received ||
781 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
783 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
785 sm->portValid = TRUE;
786 if (sm->ctx->eapol_done_cb)
787 sm->ctx->eapol_done_cb(sm->ctx->ctx);
790 #endif /* CONFIG_FIPS */
794 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
796 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
797 /* EAP layer processing; no special code is needed, since Supplicant
798 * Backend state machine is waiting for eapNoResp or eapResp to be set
799 * and these are only set in the EAP state machine when the processing
804 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
808 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
809 resp = eap_get_eapRespData(sm->eap);
811 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
816 /* Send EAP-Packet from the EAP layer to the Authenticator */
817 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
818 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
821 /* eapRespData is not used anymore, so free it here */
825 sm->dot1xSuppEapolReqIdFramesRx++;
827 sm->dot1xSuppEapolReqFramesRx++;
828 sm->dot1xSuppEapolRespFramesTx++;
829 sm->dot1xSuppEapolFramesTx++;
833 static void eapol_sm_abortSupp(struct eapol_sm *sm)
835 /* release system resources that may have been allocated for the
836 * authentication session */
837 os_free(sm->last_rx_key);
838 sm->last_rx_key = NULL;
839 wpabuf_free(sm->eapReqData);
840 sm->eapReqData = NULL;
841 eap_sm_abort(sm->eap);
845 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
847 eapol_sm_step(timeout_ctx);
851 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
853 if (sm->ctx->port_cb)
854 sm->ctx->port_cb(sm->ctx->ctx, 1);
858 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
860 if (sm->ctx->port_cb)
861 sm->ctx->port_cb(sm->ctx->ctx, 0);
866 * eapol_sm_step - EAPOL state machine step function
867 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
869 * This function is called to notify the state machine about changed external
870 * variables. It will step through the EAPOL state machines in loop to process
871 * all triggered state changes.
873 void eapol_sm_step(struct eapol_sm *sm)
877 /* In theory, it should be ok to run this in loop until !changed.
878 * However, it is better to use a limit on number of iterations to
879 * allow events (e.g., SIGTERM) to stop the program cleanly if the
880 * state machine were to generate a busy loop. */
881 for (i = 0; i < 100; i++) {
883 SM_STEP_RUN(SUPP_PAE);
885 SM_STEP_RUN(SUPP_BE);
886 if (eap_peer_sm_step(sm->eap))
893 /* restart EAPOL state machine step from timeout call in order
894 * to allow other events to be processed. */
895 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
896 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
899 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
900 int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;
901 sm->cb_status = EAPOL_CB_IN_PROGRESS;
902 sm->ctx->cb(sm, success, sm->ctx->cb_ctx);
907 #ifdef CONFIG_CTRL_IFACE
908 static const char *eapol_supp_pae_state(int state)
911 case SUPP_PAE_LOGOFF:
913 case SUPP_PAE_DISCONNECTED:
914 return "DISCONNECTED";
915 case SUPP_PAE_CONNECTING:
917 case SUPP_PAE_AUTHENTICATING:
918 return "AUTHENTICATING";
921 case SUPP_PAE_AUTHENTICATED:
922 return "AUTHENTICATED";
923 case SUPP_PAE_RESTART:
931 static const char *eapol_supp_be_state(int state)
934 case SUPP_BE_REQUEST:
936 case SUPP_BE_RESPONSE:
938 case SUPP_BE_SUCCESS:
942 case SUPP_BE_TIMEOUT:
946 case SUPP_BE_INITIALIZE:
948 case SUPP_BE_RECEIVE:
956 static const char * eapol_port_status(PortStatus status)
958 if (status == Authorized)
961 return "Unauthorized";
963 #endif /* CONFIG_CTRL_IFACE */
966 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
967 static const char * eapol_port_control(PortControl ctrl)
972 case ForceUnauthorized:
973 return "ForceUnauthorized";
974 case ForceAuthorized:
975 return "ForceAuthorized";
980 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
984 * eapol_sm_configure - Set EAPOL variables
985 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
986 * @heldPeriod: dot1xSuppHeldPeriod
987 * @authPeriod: dot1xSuppAuthPeriod
988 * @startPeriod: dot1xSuppStartPeriod
989 * @maxStart: dot1xSuppMaxStart
991 * Set configurable EAPOL state machine variables. Each variable can be set to
992 * the given value or ignored if set to -1 (to set only some of the variables).
994 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
995 int startPeriod, int maxStart)
1000 sm->heldPeriod = heldPeriod;
1001 if (authPeriod >= 0)
1002 sm->authPeriod = authPeriod;
1003 if (startPeriod >= 0)
1004 sm->startPeriod = startPeriod;
1006 sm->maxStart = maxStart;
1011 * eapol_sm_get_method_name - Get EAPOL method name
1012 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1013 * Returns: Static string containing name of current eap method or NULL
1015 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1017 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1018 sm->suppPortStatus != Authorized)
1021 return eap_sm_get_method_name(sm->eap);
1025 #ifdef CONFIG_CTRL_IFACE
1027 * eapol_sm_get_status - Get EAPOL state machine status
1028 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1029 * @buf: Buffer for status information
1030 * @buflen: Maximum buffer length
1031 * @verbose: Whether to include verbose status information
1032 * Returns: Number of bytes written to buf.
1034 * Query EAPOL state machine for status information. This function fills in a
1035 * text area with current status information from the EAPOL state machine. If
1036 * the buffer (buf) is not large enough, status information will be truncated
1037 * to fit the buffer.
1039 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1046 len = os_snprintf(buf, buflen,
1047 "Supplicant PAE state=%s\n"
1048 "suppPortStatus=%s\n",
1049 eapol_supp_pae_state(sm->SUPP_PAE_state),
1050 eapol_port_status(sm->suppPortStatus));
1051 if (len < 0 || (size_t) len >= buflen)
1055 ret = os_snprintf(buf + len, buflen - len,
1061 "Supplicant Backend state=%s\n",
1066 eapol_port_control(sm->portControl),
1067 eapol_supp_be_state(sm->SUPP_BE_state));
1068 if (ret < 0 || (size_t) ret >= buflen - len)
1073 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1080 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1081 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1082 * @buf: Buffer for MIB information
1083 * @buflen: Maximum buffer length
1084 * Returns: Number of bytes written to buf.
1086 * Query EAPOL state machine for MIB information. This function fills in a
1087 * text area with current MIB information from the EAPOL state machine. If
1088 * the buffer (buf) is not large enough, MIB information will be truncated to
1091 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1098 ret = os_snprintf(buf, buflen,
1099 "dot1xSuppPaeState=%d\n"
1100 "dot1xSuppHeldPeriod=%u\n"
1101 "dot1xSuppAuthPeriod=%u\n"
1102 "dot1xSuppStartPeriod=%u\n"
1103 "dot1xSuppMaxStart=%u\n"
1104 "dot1xSuppSuppControlledPortStatus=%s\n"
1105 "dot1xSuppBackendPaeState=%d\n",
1111 sm->suppPortStatus == Authorized ?
1112 "Authorized" : "Unauthorized",
1115 if (ret < 0 || (size_t) ret >= buflen)
1119 ret = os_snprintf(buf + len, buflen - len,
1120 "dot1xSuppEapolFramesRx=%u\n"
1121 "dot1xSuppEapolFramesTx=%u\n"
1122 "dot1xSuppEapolStartFramesTx=%u\n"
1123 "dot1xSuppEapolLogoffFramesTx=%u\n"
1124 "dot1xSuppEapolRespFramesTx=%u\n"
1125 "dot1xSuppEapolReqIdFramesRx=%u\n"
1126 "dot1xSuppEapolReqFramesRx=%u\n"
1127 "dot1xSuppInvalidEapolFramesRx=%u\n"
1128 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1129 "dot1xSuppLastEapolFrameVersion=%u\n"
1130 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1131 sm->dot1xSuppEapolFramesRx,
1132 sm->dot1xSuppEapolFramesTx,
1133 sm->dot1xSuppEapolStartFramesTx,
1134 sm->dot1xSuppEapolLogoffFramesTx,
1135 sm->dot1xSuppEapolRespFramesTx,
1136 sm->dot1xSuppEapolReqIdFramesRx,
1137 sm->dot1xSuppEapolReqFramesRx,
1138 sm->dot1xSuppInvalidEapolFramesRx,
1139 sm->dot1xSuppEapLengthErrorFramesRx,
1140 sm->dot1xSuppLastEapolFrameVersion,
1141 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1143 if (ret < 0 || (size_t) ret >= buflen - len)
1149 #endif /* CONFIG_CTRL_IFACE */
1153 * eapol_sm_rx_eapol - Process received EAPOL frames
1154 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1155 * @src: Source MAC address of the EAPOL packet
1156 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1157 * @len: Length of the EAPOL frame
1158 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1161 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1164 const struct ieee802_1x_hdr *hdr;
1165 const struct ieee802_1x_eapol_key *key;
1172 sm->dot1xSuppEapolFramesRx++;
1173 if (len < sizeof(*hdr)) {
1174 sm->dot1xSuppInvalidEapolFramesRx++;
1177 hdr = (const struct ieee802_1x_hdr *) buf;
1178 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1179 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1180 if (hdr->version < EAPOL_VERSION) {
1181 /* TODO: backwards compatibility */
1183 plen = be_to_host16(hdr->length);
1184 if (plen > len - sizeof(*hdr)) {
1185 sm->dot1xSuppEapLengthErrorFramesRx++;
1189 if (sm->conf.workaround &&
1190 plen < len - sizeof(*hdr) &&
1191 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1192 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1193 const struct eap_hdr *ehdr =
1194 (const struct eap_hdr *) (hdr + 1);
1197 elen = be_to_host16(ehdr->length);
1198 if (elen > plen && elen <= len - sizeof(*hdr)) {
1200 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1201 * packets with too short EAPOL header length field
1202 * (14 octets). This is fixed in firmware Ver.1.49.
1203 * As a workaround, fix the EAPOL header based on the
1204 * correct length in the EAP packet.
1206 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1207 "payload length based on EAP header: "
1208 "%d -> %d", (int) plen, elen);
1212 #endif /* CONFIG_WPS */
1213 data_len = plen + sizeof(*hdr);
1215 switch (hdr->type) {
1216 case IEEE802_1X_TYPE_EAP_PACKET:
1217 if (sm->cached_pmk) {
1218 /* Trying to use PMKSA caching, but Authenticator did
1219 * not seem to have a matching entry. Need to restart
1220 * EAPOL state machines.
1222 eapol_sm_abort_cached(sm);
1224 wpabuf_free(sm->eapReqData);
1225 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1226 if (sm->eapReqData) {
1227 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1229 sm->eapolEap = TRUE;
1233 case IEEE802_1X_TYPE_EAPOL_KEY:
1234 if (plen < sizeof(*key)) {
1235 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1239 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1240 if (key->type == EAPOL_KEY_TYPE_WPA ||
1241 key->type == EAPOL_KEY_TYPE_RSN) {
1242 /* WPA Supplicant takes care of this frame. */
1243 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1244 "frame in EAPOL state machines");
1248 if (key->type != EAPOL_KEY_TYPE_RC4) {
1249 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1250 "EAPOL-Key type %d", key->type);
1253 os_free(sm->last_rx_key);
1254 sm->last_rx_key = os_malloc(data_len);
1255 if (sm->last_rx_key) {
1256 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1258 os_memcpy(sm->last_rx_key, buf, data_len);
1259 sm->last_rx_key_len = data_len;
1265 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1267 sm->dot1xSuppInvalidEapolFramesRx++;
1276 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1277 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1279 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1280 * component, e.g., WPA. This will update the statistics.
1282 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1285 sm->dot1xSuppEapolFramesTx++;
1290 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1291 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1292 * @enabled: New portEnabled value
1294 * Notify EAPOL state machine about new portEnabled value.
1296 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1300 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1301 "portEnabled=%d", enabled);
1302 sm->portEnabled = enabled;
1308 * eapol_sm_notify_portValid - Notification about portValid change
1309 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1310 * @valid: New portValid value
1312 * Notify EAPOL state machine about new portValid value.
1314 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1318 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1319 "portValid=%d", valid);
1320 sm->portValid = valid;
1326 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1327 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1328 * @success: %TRUE = set success, %FALSE = clear success
1330 * Notify the EAPOL state machine that external event has forced EAP state to
1331 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1333 * This function is called to update EAP state when WPA-PSK key handshake has
1334 * been completed successfully since WPA-PSK does not use EAP state machine.
1336 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1340 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1341 "EAP success=%d", success);
1342 sm->eapSuccess = success;
1343 sm->altAccept = success;
1345 eap_notify_success(sm->eap);
1351 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1352 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1353 * @fail: %TRUE = set failure, %FALSE = clear failure
1355 * Notify EAPOL state machine that external event has forced EAP state to
1356 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1358 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1362 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1363 "EAP fail=%d", fail);
1365 sm->altReject = fail;
1371 * eapol_sm_notify_config - Notification of EAPOL configuration change
1372 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1373 * @config: Pointer to current network EAP configuration
1374 * @conf: Pointer to EAPOL configuration data
1376 * Notify EAPOL state machine that configuration has changed. config will be
1377 * stored as a backpointer to network configuration. This can be %NULL to clear
1378 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1379 * data. If conf is %NULL, this part of the configuration change will be
1382 void eapol_sm_notify_config(struct eapol_sm *sm,
1383 struct eap_peer_config *config,
1384 const struct eapol_config *conf)
1389 sm->config = config;
1394 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1395 sm->conf.required_keys = conf->required_keys;
1396 sm->conf.fast_reauth = conf->fast_reauth;
1397 sm->conf.workaround = conf->workaround;
1399 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1400 eap_set_workaround(sm->eap, conf->workaround);
1401 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1407 * eapol_sm_get_key - Get master session key (MSK) from EAP
1408 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1409 * @key: Pointer for key buffer
1410 * @len: Number of bytes to copy to key
1411 * Returns: 0 on success (len of key available), maximum available key len
1412 * (>0) if key is available but it is shorter than len, or -1 on failure.
1414 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1415 * is available only after a successful authentication.
1417 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1422 if (sm == NULL || !eap_key_available(sm->eap)) {
1423 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1426 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1427 if (eap_key == NULL) {
1428 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1431 if (len > eap_len) {
1432 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1433 "available (len=%lu)",
1434 (unsigned long) len, (unsigned long) eap_len);
1437 os_memcpy(key, eap_key, len);
1438 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1439 (unsigned long) len);
1445 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1446 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1447 * @logoff: Whether command was logoff
1449 * Notify EAPOL state machines that user requested logon/logoff.
1451 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1454 sm->userLogoff = logoff;
1461 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1462 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1464 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1465 * to move EAPOL and EAP state machines into authenticated/successful state.
1467 void eapol_sm_notify_cached(struct eapol_sm *sm)
1471 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1472 sm->eapSuccess = TRUE;
1473 eap_notify_success(sm->eap);
1479 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1480 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1481 * @attempt: Whether PMKSA caching is tried
1483 * Notify EAPOL state machines whether PMKSA caching is used.
1485 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
1490 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1491 sm->cached_pmk = TRUE;
1493 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
1494 sm->cached_pmk = FALSE;
1499 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1501 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1502 "doing full EAP authentication");
1505 sm->cached_pmk = FALSE;
1506 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1507 sm->suppPortStatus = Unauthorized;
1508 eapol_sm_set_port_unauthorized(sm);
1510 /* Make sure we do not start sending EAPOL-Start frames first, but
1511 * instead move to RESTART state to start EAPOL authentication. */
1513 eapol_enable_timer_tick(sm);
1515 if (sm->ctx->aborted_cached)
1516 sm->ctx->aborted_cached(sm->ctx->ctx);
1521 * eapol_sm_register_scard_ctx - Notification of smart card context
1522 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1523 * @ctx: Context data for smart card operations
1525 * Notify EAPOL state machines of context data for smart card operations. This
1526 * context data will be used as a parameter for scard_*() functions.
1528 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1531 sm->ctx->scard_ctx = ctx;
1532 eap_register_scard_ctx(sm->eap, ctx);
1538 * eapol_sm_notify_portControl - Notification of portControl changes
1539 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1540 * @portControl: New value for portControl variable
1542 * Notify EAPOL state machines that portControl variable has changed.
1544 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1548 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1549 "portControl=%s", eapol_port_control(portControl));
1550 sm->portControl = portControl;
1556 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1557 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1559 * Notify EAPOL state machines that a monitor was attached to the control
1560 * interface to trigger re-sending of pending requests for user input.
1562 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1566 eap_sm_notify_ctrl_attached(sm->eap);
1571 * eapol_sm_notify_ctrl_response - Notification of received user input
1572 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1574 * Notify EAPOL state machines that a control response, i.e., user
1575 * input, was received in order to trigger retrying of a pending EAP request.
1577 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1581 if (sm->eapReqData && !sm->eapReq) {
1582 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1583 "input) notification - retrying pending EAP "
1585 sm->eapolEap = TRUE;
1593 * eapol_sm_request_reauth - Request reauthentication
1594 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1596 * This function can be used to request EAPOL reauthentication, e.g., when the
1597 * current PMKSA entry is nearing expiration.
1599 void eapol_sm_request_reauth(struct eapol_sm *sm)
1601 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1603 eapol_sm_txStart(sm);
1608 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1609 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1610 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1611 * machine loop (eapol_sm_step())
1613 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1614 * successful authentication. This is used to recover from dropped EAP-Success
1617 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1621 eap_notify_lower_layer_success(sm->eap);
1628 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1629 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1631 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1634 eap_invalidate_cached_session(sm->eap);
1638 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1640 struct eapol_sm *sm = ctx;
1641 return sm ? sm->config : NULL;
1645 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1647 struct eapol_sm *sm = ctx;
1648 if (sm == NULL || sm->eapReqData == NULL)
1651 return sm->eapReqData;
1655 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1657 struct eapol_sm *sm = ctx;
1661 case EAPOL_eapSuccess:
1662 return sm->eapSuccess;
1663 case EAPOL_eapRestart:
1664 return sm->eapRestart;
1669 case EAPOL_eapNoResp:
1670 return sm->eapNoResp;
1673 case EAPOL_portEnabled:
1674 return sm->portEnabled;
1675 case EAPOL_altAccept:
1676 return sm->altAccept;
1677 case EAPOL_altReject:
1678 return sm->altReject;
1684 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1687 struct eapol_sm *sm = ctx;
1691 case EAPOL_eapSuccess:
1692 sm->eapSuccess = value;
1694 case EAPOL_eapRestart:
1695 sm->eapRestart = value;
1698 sm->eapFail = value;
1701 sm->eapResp = value;
1703 case EAPOL_eapNoResp:
1704 sm->eapNoResp = value;
1709 case EAPOL_portEnabled:
1710 sm->portEnabled = value;
1712 case EAPOL_altAccept:
1713 sm->altAccept = value;
1715 case EAPOL_altReject:
1716 sm->altReject = value;
1722 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1724 struct eapol_sm *sm = ctx;
1728 case EAPOL_idleWhile:
1729 return sm->idleWhile;
1735 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1738 struct eapol_sm *sm = ctx;
1742 case EAPOL_idleWhile:
1743 sm->idleWhile = value;
1744 if (sm->idleWhile > 0)
1745 eapol_enable_timer_tick(sm);
1751 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1753 #ifndef CONFIG_NO_CONFIG_BLOBS
1754 struct eapol_sm *sm = ctx;
1755 if (sm && sm->ctx && sm->ctx->set_config_blob)
1756 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1757 #endif /* CONFIG_NO_CONFIG_BLOBS */
1761 static const struct wpa_config_blob *
1762 eapol_sm_get_config_blob(void *ctx, const char *name)
1764 #ifndef CONFIG_NO_CONFIG_BLOBS
1765 struct eapol_sm *sm = ctx;
1766 if (sm && sm->ctx && sm->ctx->get_config_blob)
1767 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1770 #else /* CONFIG_NO_CONFIG_BLOBS */
1772 #endif /* CONFIG_NO_CONFIG_BLOBS */
1776 static void eapol_sm_notify_pending(void *ctx)
1778 struct eapol_sm *sm = ctx;
1781 if (sm->eapReqData && !sm->eapReq) {
1782 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1783 "state machine - retrying pending EAP Request");
1784 sm->eapolEap = TRUE;
1791 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1792 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1795 struct eapol_sm *sm = ctx;
1796 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1797 if (sm->ctx->eap_param_needed)
1798 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1800 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1801 #define eapol_sm_eap_param_needed NULL
1802 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1804 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
1805 const char *cert_hash,
1806 const struct wpabuf *cert)
1808 struct eapol_sm *sm = ctx;
1809 if (sm->ctx->cert_cb)
1810 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
1815 static void eapol_sm_notify_status(void *ctx, const char *status,
1816 const char *parameter)
1818 struct eapol_sm *sm = ctx;
1820 if (sm->ctx->status_cb)
1821 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
1825 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
1827 struct eapol_sm *sm = ctx;
1829 if (sm->ctx->set_anon_id)
1830 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
1834 static struct eapol_callbacks eapol_cb =
1836 eapol_sm_get_config,
1841 eapol_sm_get_eapReqData,
1842 eapol_sm_set_config_blob,
1843 eapol_sm_get_config_blob,
1844 eapol_sm_notify_pending,
1845 eapol_sm_eap_param_needed,
1846 eapol_sm_notify_cert,
1847 eapol_sm_notify_status,
1848 eapol_sm_set_anon_id
1853 * eapol_sm_init - Initialize EAPOL state machine
1854 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
1855 * and EAPOL state machine will free it in eapol_sm_deinit()
1856 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
1858 * Allocate and initialize an EAPOL state machine.
1860 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
1862 struct eapol_sm *sm;
1863 struct eap_config conf;
1864 sm = os_zalloc(sizeof(*sm));
1869 sm->portControl = Auto;
1871 /* Supplicant PAE state machine */
1872 sm->heldPeriod = 60;
1873 sm->startPeriod = 30;
1876 /* Supplicant Backend state machine */
1877 sm->authPeriod = 30;
1879 os_memset(&conf, 0, sizeof(conf));
1880 conf.opensc_engine_path = ctx->opensc_engine_path;
1881 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
1882 conf.pkcs11_module_path = ctx->pkcs11_module_path;
1883 conf.wps = ctx->wps;
1884 conf.cert_in_cb = ctx->cert_in_cb;
1886 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
1887 if (sm->eap == NULL) {
1892 /* Initialize EAPOL state machines */
1893 sm->initialize = TRUE;
1895 sm->initialize = FALSE;
1898 sm->timer_tick_enabled = 1;
1899 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
1906 * eapol_sm_deinit - Deinitialize EAPOL state machine
1907 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1909 * Deinitialize and free EAPOL state machine.
1911 void eapol_sm_deinit(struct eapol_sm *sm)
1915 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
1916 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
1917 eap_peer_sm_deinit(sm->eap);
1918 os_free(sm->last_rx_key);
1919 wpabuf_free(sm->eapReqData);
1925 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
1926 struct ext_password_data *ext)
1929 eap_sm_set_ext_pw_ctx(sm->eap, ext);
1933 int eapol_sm_failed(struct eapol_sm *sm)
1937 return !sm->eapSuccess && sm->eapFail;