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_proxy.h"
20 #include "eapol_supp_sm.h"
22 #define STATE_MACHINE_DATA struct eapol_sm
23 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
26 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
29 * struct eapol_sm - Internal data for EAPOL state machines
33 unsigned int authWhile;
34 unsigned int heldWhile;
35 unsigned int startWhen;
36 unsigned int idleWhile; /* for EAP state machine */
37 int timer_tick_enabled;
39 /* Global variables */
46 PortControl portControl;
48 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
56 /* Supplicant PAE state machine */
59 SUPP_PAE_DISCONNECTED = 1,
61 SUPP_PAE_CONNECTING = 3,
62 SUPP_PAE_AUTHENTICATING = 4,
63 SUPP_PAE_AUTHENTICATED = 5,
67 SUPP_PAE_S_FORCE_AUTH = 9,
68 SUPP_PAE_S_FORCE_UNAUTH = 10
69 } SUPP_PAE_state; /* dot1xSuppPaeState */
73 unsigned int startCount;
75 PortControl sPortMode;
77 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
78 unsigned int startPeriod; /* dot1xSuppStartPeriod */
79 unsigned int maxStart; /* dot1xSuppMaxStart */
81 /* Key Receive state machine */
84 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
89 /* Supplicant Backend state machine */
92 SUPP_BE_INITIALIZE = 1,
100 } SUPP_BE_state; /* dot1xSuppBackendPaeState */
106 unsigned int authPeriod; /* dot1xSuppAuthPeriod */
109 unsigned int dot1xSuppEapolFramesRx;
110 unsigned int dot1xSuppEapolFramesTx;
111 unsigned int dot1xSuppEapolStartFramesTx;
112 unsigned int dot1xSuppEapolLogoffFramesTx;
113 unsigned int dot1xSuppEapolRespFramesTx;
114 unsigned int dot1xSuppEapolReqIdFramesRx;
115 unsigned int dot1xSuppEapolReqFramesRx;
116 unsigned int dot1xSuppInvalidEapolFramesRx;
117 unsigned int dot1xSuppEapLengthErrorFramesRx;
118 unsigned int dot1xSuppLastEapolFrameVersion;
119 unsigned char dot1xSuppLastEapolFrameSource[6];
121 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
124 struct eap_peer_config *config;
127 size_t last_rx_key_len;
128 struct wpabuf *eapReqData; /* for EAP */
129 Boolean altAccept; /* for EAP */
130 Boolean altReject; /* for EAP */
131 Boolean replay_counter_valid;
132 u8 last_replay_counter[16];
133 struct eapol_config conf;
134 struct eapol_ctx *ctx;
135 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
139 Boolean unicast_key_received, broadcast_key_received;
141 Boolean force_authorized_update;
143 #ifdef CONFIG_EAP_PROXY
144 Boolean use_eap_proxy;
145 struct eap_proxy_sm *eap_proxy;
146 #endif /* CONFIG_EAP_PROXY */
150 static void eapol_sm_txLogoff(struct eapol_sm *sm);
151 static void eapol_sm_txStart(struct eapol_sm *sm);
152 static void eapol_sm_processKey(struct eapol_sm *sm);
153 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
154 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
155 static void eapol_sm_abortSupp(struct eapol_sm *sm);
156 static void eapol_sm_abort_cached(struct eapol_sm *sm);
157 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
158 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
159 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
162 /* Port Timers state machine - implemented as a function that will be called
163 * once a second as a registered event loop timeout */
164 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
166 struct eapol_sm *sm = timeout_ctx;
168 if (sm->authWhile > 0) {
170 if (sm->authWhile == 0)
171 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
173 if (sm->heldWhile > 0) {
175 if (sm->heldWhile == 0)
176 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
178 if (sm->startWhen > 0) {
180 if (sm->startWhen == 0)
181 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
183 if (sm->idleWhile > 0) {
185 if (sm->idleWhile == 0)
186 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
189 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
190 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
193 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
194 sm->timer_tick_enabled = 0;
200 static void eapol_enable_timer_tick(struct eapol_sm *sm)
202 if (sm->timer_tick_enabled)
204 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
205 sm->timer_tick_enabled = 1;
206 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
207 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
211 SM_STATE(SUPP_PAE, LOGOFF)
213 SM_ENTRY(SUPP_PAE, LOGOFF);
214 eapol_sm_txLogoff(sm);
215 sm->logoffSent = TRUE;
216 eapol_sm_set_port_unauthorized(sm);
220 SM_STATE(SUPP_PAE, DISCONNECTED)
222 SM_ENTRY(SUPP_PAE, DISCONNECTED);
223 sm->sPortMode = Auto;
225 sm->logoffSent = FALSE;
226 eapol_sm_set_port_unauthorized(sm);
227 sm->suppAbort = TRUE;
229 sm->unicast_key_received = FALSE;
230 sm->broadcast_key_received = FALSE;
233 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
234 * allows the timer tick to be stopped more quickly when the port is
235 * not enabled. Since this variable is used only within HELD state,
236 * clearing it on initialization does not change actual state machine
243 SM_STATE(SUPP_PAE, CONNECTING)
245 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
246 SM_ENTRY(SUPP_PAE, CONNECTING);
248 sm->startWhen = sm->startPeriod;
252 * Do not send EAPOL-Start immediately since in most cases,
253 * Authenticator is going to start authentication immediately
254 * after association and an extra EAPOL-Start is just going to
255 * delay authentication. Use a short timeout to send the first
256 * EAPOL-Start if Authenticator does not start authentication.
258 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
259 /* Reduce latency on starting WPS negotiation. */
260 wpa_printf(MSG_DEBUG,
261 "EAPOL: Using shorter startWhen for WPS");
267 eapol_enable_timer_tick(sm);
268 sm->eapolEap = FALSE;
270 eapol_sm_txStart(sm);
274 SM_STATE(SUPP_PAE, AUTHENTICATING)
276 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
278 sm->suppSuccess = FALSE;
279 sm->suppFail = FALSE;
280 sm->suppTimeout = FALSE;
283 sm->suppStart = TRUE;
287 SM_STATE(SUPP_PAE, HELD)
289 SM_ENTRY(SUPP_PAE, HELD);
290 sm->heldWhile = sm->heldPeriod;
291 eapol_enable_timer_tick(sm);
292 eapol_sm_set_port_unauthorized(sm);
293 sm->cb_status = EAPOL_CB_FAILURE;
297 SM_STATE(SUPP_PAE, AUTHENTICATED)
299 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
300 eapol_sm_set_port_authorized(sm);
301 sm->cb_status = EAPOL_CB_SUCCESS;
305 SM_STATE(SUPP_PAE, RESTART)
307 SM_ENTRY(SUPP_PAE, RESTART);
308 sm->eapRestart = TRUE;
312 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
314 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
315 eapol_sm_set_port_authorized(sm);
316 sm->sPortMode = ForceAuthorized;
320 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
322 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
323 eapol_sm_set_port_unauthorized(sm);
324 sm->sPortMode = ForceUnauthorized;
325 eapol_sm_txLogoff(sm);
331 if ((sm->userLogoff && !sm->logoffSent) &&
332 !(sm->initialize || !sm->portEnabled))
333 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
334 else if (((sm->portControl == Auto) &&
335 (sm->sPortMode != sm->portControl)) ||
336 sm->initialize || !sm->portEnabled)
337 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
338 else if ((sm->portControl == ForceAuthorized) &&
339 (sm->sPortMode != sm->portControl) &&
340 !(sm->initialize || !sm->portEnabled))
341 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
342 else if ((sm->portControl == ForceUnauthorized) &&
343 (sm->sPortMode != sm->portControl) &&
344 !(sm->initialize || !sm->portEnabled))
345 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
346 else switch (sm->SUPP_PAE_state) {
347 case SUPP_PAE_UNKNOWN:
349 case SUPP_PAE_LOGOFF:
351 SM_ENTER(SUPP_PAE, DISCONNECTED);
353 case SUPP_PAE_DISCONNECTED:
354 SM_ENTER(SUPP_PAE, CONNECTING);
356 case SUPP_PAE_CONNECTING:
357 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
358 SM_ENTER(SUPP_PAE, CONNECTING);
359 else if (sm->startWhen == 0 &&
360 sm->startCount >= sm->maxStart &&
362 SM_ENTER(SUPP_PAE, AUTHENTICATED);
363 else if (sm->eapSuccess || sm->eapFail)
364 SM_ENTER(SUPP_PAE, AUTHENTICATING);
365 else if (sm->eapolEap)
366 SM_ENTER(SUPP_PAE, RESTART);
367 else if (sm->startWhen == 0 &&
368 sm->startCount >= sm->maxStart &&
370 SM_ENTER(SUPP_PAE, HELD);
372 case SUPP_PAE_AUTHENTICATING:
373 if (sm->eapSuccess && !sm->portValid &&
374 sm->conf.accept_802_1x_keys &&
375 sm->conf.required_keys == 0) {
376 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
377 "plaintext connection; no EAPOL-Key frames "
379 sm->portValid = TRUE;
380 if (sm->ctx->eapol_done_cb)
381 sm->ctx->eapol_done_cb(sm->ctx->ctx);
383 if (sm->eapSuccess && sm->portValid)
384 SM_ENTER(SUPP_PAE, AUTHENTICATED);
385 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
386 SM_ENTER(SUPP_PAE, HELD);
387 else if (sm->suppTimeout)
388 SM_ENTER(SUPP_PAE, CONNECTING);
391 if (sm->heldWhile == 0)
392 SM_ENTER(SUPP_PAE, CONNECTING);
393 else if (sm->eapolEap)
394 SM_ENTER(SUPP_PAE, RESTART);
396 case SUPP_PAE_AUTHENTICATED:
397 if (sm->eapolEap && sm->portValid)
398 SM_ENTER(SUPP_PAE, RESTART);
399 else if (!sm->portValid)
400 SM_ENTER(SUPP_PAE, DISCONNECTED);
402 case SUPP_PAE_RESTART:
404 SM_ENTER(SUPP_PAE, AUTHENTICATING);
406 case SUPP_PAE_S_FORCE_AUTH:
408 case SUPP_PAE_S_FORCE_UNAUTH:
414 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
416 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
420 SM_STATE(KEY_RX, KEY_RECEIVE)
422 SM_ENTRY(KEY_RX, KEY_RECEIVE);
423 eapol_sm_processKey(sm);
430 if (sm->initialize || !sm->portEnabled)
431 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
432 switch (sm->KEY_RX_state) {
435 case KEY_RX_NO_KEY_RECEIVE:
437 SM_ENTER(KEY_RX, KEY_RECEIVE);
439 case KEY_RX_KEY_RECEIVE:
441 SM_ENTER(KEY_RX, KEY_RECEIVE);
447 SM_STATE(SUPP_BE, REQUEST)
449 SM_ENTRY(SUPP_BE, REQUEST);
452 eapol_sm_getSuppRsp(sm);
456 SM_STATE(SUPP_BE, RESPONSE)
458 SM_ENTRY(SUPP_BE, RESPONSE);
459 eapol_sm_txSuppRsp(sm);
464 SM_STATE(SUPP_BE, SUCCESS)
466 SM_ENTRY(SUPP_BE, SUCCESS);
468 sm->suppSuccess = TRUE;
470 #ifdef CONFIG_EAP_PROXY
471 if (sm->use_eap_proxy) {
472 if (eap_proxy_key_available(sm->eap_proxy)) {
473 /* New key received - clear IEEE 802.1X EAPOL-Key replay
475 sm->replay_counter_valid = FALSE;
479 #endif /* CONFIG_EAP_PROXY */
481 if (eap_key_available(sm->eap)) {
482 /* New key received - clear IEEE 802.1X EAPOL-Key replay
484 sm->replay_counter_valid = FALSE;
489 SM_STATE(SUPP_BE, FAIL)
491 SM_ENTRY(SUPP_BE, FAIL);
496 SM_STATE(SUPP_BE, TIMEOUT)
498 SM_ENTRY(SUPP_BE, TIMEOUT);
499 sm->suppTimeout = TRUE;
503 SM_STATE(SUPP_BE, IDLE)
505 SM_ENTRY(SUPP_BE, IDLE);
506 sm->suppStart = FALSE;
507 sm->initial_req = TRUE;
511 SM_STATE(SUPP_BE, INITIALIZE)
513 SM_ENTRY(SUPP_BE, INITIALIZE);
514 eapol_sm_abortSupp(sm);
515 sm->suppAbort = FALSE;
518 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
519 * allows the timer tick to be stopped more quickly when the port is
520 * not enabled. Since this variable is used only within RECEIVE state,
521 * clearing it on initialization does not change actual state machine
528 SM_STATE(SUPP_BE, RECEIVE)
530 SM_ENTRY(SUPP_BE, RECEIVE);
531 sm->authWhile = sm->authPeriod;
532 eapol_enable_timer_tick(sm);
533 sm->eapolEap = FALSE;
534 sm->eapNoResp = FALSE;
535 sm->initial_req = FALSE;
541 if (sm->initialize || sm->suppAbort)
542 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
543 else switch (sm->SUPP_BE_state) {
544 case SUPP_BE_UNKNOWN:
546 case SUPP_BE_REQUEST:
548 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
549 * and SUCCESS based on eapFail and eapSuccess, respectively.
550 * However, IEEE Std 802.1X-2004 is also specifying that
551 * eapNoResp should be set in conjunction with eapSuccess and
552 * eapFail which would mean that more than one of the
553 * transitions here would be activated at the same time.
554 * Skipping RESPONSE and/or RECEIVE states in these cases can
555 * cause problems and the direct transitions to do not seem
556 * correct. Because of this, the conditions for these
557 * transitions are verified only after eapNoResp. They are
558 * unlikely to be used since eapNoResp should always be set if
559 * either of eapSuccess or eapFail is set.
561 if (sm->eapResp && sm->eapNoResp) {
562 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
563 "eapResp and eapNoResp set?!");
566 SM_ENTER(SUPP_BE, RESPONSE);
567 else if (sm->eapNoResp)
568 SM_ENTER(SUPP_BE, RECEIVE);
569 else if (sm->eapFail)
570 SM_ENTER(SUPP_BE, FAIL);
571 else if (sm->eapSuccess)
572 SM_ENTER(SUPP_BE, SUCCESS);
574 case SUPP_BE_RESPONSE:
575 SM_ENTER(SUPP_BE, RECEIVE);
577 case SUPP_BE_SUCCESS:
578 SM_ENTER(SUPP_BE, IDLE);
581 SM_ENTER(SUPP_BE, IDLE);
583 case SUPP_BE_TIMEOUT:
584 SM_ENTER(SUPP_BE, IDLE);
587 if (sm->eapFail && sm->suppStart)
588 SM_ENTER(SUPP_BE, FAIL);
589 else if (sm->eapolEap && sm->suppStart)
590 SM_ENTER(SUPP_BE, REQUEST);
591 else if (sm->eapSuccess && sm->suppStart)
592 SM_ENTER(SUPP_BE, SUCCESS);
594 case SUPP_BE_INITIALIZE:
595 SM_ENTER(SUPP_BE, IDLE);
597 case SUPP_BE_RECEIVE:
599 SM_ENTER(SUPP_BE, REQUEST);
600 else if (sm->eapFail)
601 SM_ENTER(SUPP_BE, FAIL);
602 else if (sm->authWhile == 0)
603 SM_ENTER(SUPP_BE, TIMEOUT);
604 else if (sm->eapSuccess)
605 SM_ENTER(SUPP_BE, SUCCESS);
611 static void eapol_sm_txLogoff(struct eapol_sm *sm)
613 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
614 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
615 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
616 sm->dot1xSuppEapolLogoffFramesTx++;
617 sm->dot1xSuppEapolFramesTx++;
621 static void eapol_sm_txStart(struct eapol_sm *sm)
623 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
624 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
625 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
626 sm->dot1xSuppEapolStartFramesTx++;
627 sm->dot1xSuppEapolFramesTx++;
631 #define IEEE8021X_ENCR_KEY_LEN 32
632 #define IEEE8021X_SIGN_KEY_LEN 32
634 struct eap_key_data {
635 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
636 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
640 static void eapol_sm_processKey(struct eapol_sm *sm)
643 struct ieee802_1x_hdr *hdr;
644 struct ieee802_1x_eapol_key *key;
645 struct eap_key_data keydata;
646 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
647 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
648 int key_len, res, sign_key_len, encr_key_len;
652 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
653 if (sm->last_rx_key == NULL)
656 if (!sm->conf.accept_802_1x_keys) {
657 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
658 " even though this was not accepted - "
659 "ignoring this packet");
663 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
665 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
666 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
667 plen = be_to_host16(hdr->length);
668 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
669 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
672 rx_key_length = WPA_GET_BE16(key->key_length);
673 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
674 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
675 hdr->version, hdr->type, be_to_host16(hdr->length),
676 key->type, rx_key_length, key->key_index);
678 eapol_sm_notify_lower_layer_success(sm, 1);
679 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
680 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
681 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
683 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
684 "decrypting EAPOL-Key keys");
688 /* LEAP derives only 16 bytes of keying material. */
689 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
691 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
692 "master key for decrypting EAPOL-Key keys");
697 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
699 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
700 "data for decrypting EAPOL-Key keys (res=%d)", res);
704 /* The key replay_counter must increase when same master key */
705 if (sm->replay_counter_valid &&
706 os_memcmp(sm->last_replay_counter, key->replay_counter,
707 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
708 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
709 "not increase - ignoring key");
710 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
711 sm->last_replay_counter,
712 IEEE8021X_REPLAY_COUNTER_LEN);
713 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
714 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
718 /* Verify key signature (HMAC-MD5) */
719 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
720 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
721 hmac_md5(keydata.sign_key, sign_key_len,
722 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
724 if (os_memcmp_const(orig_key_sign, key->key_signature,
725 IEEE8021X_KEY_SIGN_LEN) != 0) {
726 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
728 os_memcpy(key->key_signature, orig_key_sign,
729 IEEE8021X_KEY_SIGN_LEN);
732 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
734 key_len = plen - sizeof(*key);
735 if (key_len > 32 || rx_key_length > 32) {
736 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
737 key_len ? key_len : rx_key_length);
740 if (key_len == rx_key_length) {
741 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
742 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
744 os_memcpy(datakey, key + 1, key_len);
745 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
747 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
749 } else if (key_len == 0) {
751 * IEEE 802.1X-2004 specifies that least significant Key Length
752 * octets from MS-MPPE-Send-Key are used as the key if the key
753 * data is not present. This seems to be meaning the beginning
754 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
755 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
756 * Anyway, taking the beginning of the keying material from EAP
757 * seems to interoperate with Authenticators.
759 key_len = rx_key_length;
760 os_memcpy(datakey, keydata.encr_key, key_len);
761 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
762 "material data encryption key",
765 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
766 "(key_length=%d)", key_len, rx_key_length);
770 sm->replay_counter_valid = TRUE;
771 os_memcpy(sm->last_replay_counter, key->replay_counter,
772 IEEE8021X_REPLAY_COUNTER_LEN);
774 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
776 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
777 "unicast" : "broadcast",
778 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
780 if (sm->ctx->set_wep_key &&
781 sm->ctx->set_wep_key(sm->ctx->ctx,
782 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
783 key->key_index & IEEE8021X_KEY_INDEX_MASK,
784 datakey, key_len) < 0) {
785 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
788 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
789 sm->unicast_key_received = TRUE;
791 sm->broadcast_key_received = TRUE;
793 if ((sm->unicast_key_received ||
794 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
795 (sm->broadcast_key_received ||
796 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
798 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
800 sm->portValid = TRUE;
801 if (sm->ctx->eapol_done_cb)
802 sm->ctx->eapol_done_cb(sm->ctx->ctx);
805 #endif /* CONFIG_FIPS */
809 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
811 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
812 /* EAP layer processing; no special code is needed, since Supplicant
813 * Backend state machine is waiting for eapNoResp or eapResp to be set
814 * and these are only set in the EAP state machine when the processing
819 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
823 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
825 #ifdef CONFIG_EAP_PROXY
826 if (sm->use_eap_proxy) {
827 /* Get EAP Response from EAP Proxy */
828 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
830 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
831 "response data not available");
835 #endif /* CONFIG_EAP_PROXY */
837 resp = eap_get_eapRespData(sm->eap);
839 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
844 /* Send EAP-Packet from the EAP layer to the Authenticator */
845 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
846 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
849 /* eapRespData is not used anymore, so free it here */
853 sm->dot1xSuppEapolReqIdFramesRx++;
855 sm->dot1xSuppEapolReqFramesRx++;
856 sm->dot1xSuppEapolRespFramesTx++;
857 sm->dot1xSuppEapolFramesTx++;
861 static void eapol_sm_abortSupp(struct eapol_sm *sm)
863 /* release system resources that may have been allocated for the
864 * authentication session */
865 os_free(sm->last_rx_key);
866 sm->last_rx_key = NULL;
867 wpabuf_free(sm->eapReqData);
868 sm->eapReqData = NULL;
869 eap_sm_abort(sm->eap);
873 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
875 eapol_sm_step(timeout_ctx);
879 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
883 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
884 sm->force_authorized_update = FALSE;
885 sm->suppPortStatus = Authorized;
886 if (cb && sm->ctx->port_cb)
887 sm->ctx->port_cb(sm->ctx->ctx, 1);
891 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
895 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
896 sm->force_authorized_update = FALSE;
897 sm->suppPortStatus = Unauthorized;
898 if (cb && sm->ctx->port_cb)
899 sm->ctx->port_cb(sm->ctx->ctx, 0);
904 * eapol_sm_step - EAPOL state machine step function
905 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
907 * This function is called to notify the state machine about changed external
908 * variables. It will step through the EAPOL state machines in loop to process
909 * all triggered state changes.
911 void eapol_sm_step(struct eapol_sm *sm)
915 /* In theory, it should be ok to run this in loop until !changed.
916 * However, it is better to use a limit on number of iterations to
917 * allow events (e.g., SIGTERM) to stop the program cleanly if the
918 * state machine were to generate a busy loop. */
919 for (i = 0; i < 100; i++) {
921 SM_STEP_RUN(SUPP_PAE);
923 SM_STEP_RUN(SUPP_BE);
924 #ifdef CONFIG_EAP_PROXY
925 if (sm->use_eap_proxy) {
926 /* Drive the EAP proxy state machine */
927 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
930 #endif /* CONFIG_EAP_PROXY */
931 if (eap_peer_sm_step(sm->eap))
938 /* restart EAPOL state machine step from timeout call in order
939 * to allow other events to be processed. */
940 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
941 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
944 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
945 enum eapol_supp_result result;
946 if (sm->cb_status == EAPOL_CB_SUCCESS)
947 result = EAPOL_SUPP_RESULT_SUCCESS;
948 else if (eap_peer_was_failure_expected(sm->eap))
949 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
951 result = EAPOL_SUPP_RESULT_FAILURE;
952 sm->cb_status = EAPOL_CB_IN_PROGRESS;
953 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
958 #ifdef CONFIG_CTRL_IFACE
959 static const char *eapol_supp_pae_state(int state)
962 case SUPP_PAE_LOGOFF:
964 case SUPP_PAE_DISCONNECTED:
965 return "DISCONNECTED";
966 case SUPP_PAE_CONNECTING:
968 case SUPP_PAE_AUTHENTICATING:
969 return "AUTHENTICATING";
972 case SUPP_PAE_AUTHENTICATED:
973 return "AUTHENTICATED";
974 case SUPP_PAE_RESTART:
982 static const char *eapol_supp_be_state(int state)
985 case SUPP_BE_REQUEST:
987 case SUPP_BE_RESPONSE:
989 case SUPP_BE_SUCCESS:
993 case SUPP_BE_TIMEOUT:
997 case SUPP_BE_INITIALIZE:
999 case SUPP_BE_RECEIVE:
1007 static const char * eapol_port_status(PortStatus status)
1009 if (status == Authorized)
1010 return "Authorized";
1012 return "Unauthorized";
1014 #endif /* CONFIG_CTRL_IFACE */
1017 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1018 static const char * eapol_port_control(PortControl ctrl)
1023 case ForceUnauthorized:
1024 return "ForceUnauthorized";
1025 case ForceAuthorized:
1026 return "ForceAuthorized";
1031 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1035 * eapol_sm_configure - Set EAPOL variables
1036 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1037 * @heldPeriod: dot1xSuppHeldPeriod
1038 * @authPeriod: dot1xSuppAuthPeriod
1039 * @startPeriod: dot1xSuppStartPeriod
1040 * @maxStart: dot1xSuppMaxStart
1042 * Set configurable EAPOL state machine variables. Each variable can be set to
1043 * the given value or ignored if set to -1 (to set only some of the variables).
1045 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1046 int startPeriod, int maxStart)
1050 if (heldPeriod >= 0)
1051 sm->heldPeriod = heldPeriod;
1052 if (authPeriod >= 0)
1053 sm->authPeriod = authPeriod;
1054 if (startPeriod >= 0)
1055 sm->startPeriod = startPeriod;
1057 sm->maxStart = maxStart;
1062 * eapol_sm_get_method_name - Get EAPOL method name
1063 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1064 * Returns: Static string containing name of current eap method or NULL
1066 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1068 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1069 sm->suppPortStatus != Authorized)
1072 return eap_sm_get_method_name(sm->eap);
1076 #ifdef CONFIG_CTRL_IFACE
1078 * eapol_sm_get_status - Get EAPOL state machine status
1079 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1080 * @buf: Buffer for status information
1081 * @buflen: Maximum buffer length
1082 * @verbose: Whether to include verbose status information
1083 * Returns: Number of bytes written to buf.
1085 * Query EAPOL state machine for status information. This function fills in a
1086 * text area with current status information from the EAPOL state machine. If
1087 * the buffer (buf) is not large enough, status information will be truncated
1088 * to fit the buffer.
1090 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1097 len = os_snprintf(buf, buflen,
1098 "Supplicant PAE state=%s\n"
1099 "suppPortStatus=%s\n",
1100 eapol_supp_pae_state(sm->SUPP_PAE_state),
1101 eapol_port_status(sm->suppPortStatus));
1102 if (len < 0 || (size_t) len >= buflen)
1106 ret = os_snprintf(buf + len, buflen - len,
1112 "Supplicant Backend state=%s\n",
1117 eapol_port_control(sm->portControl),
1118 eapol_supp_be_state(sm->SUPP_BE_state));
1119 if (ret < 0 || (size_t) ret >= buflen - len)
1124 #ifdef CONFIG_EAP_PROXY
1125 if (sm->use_eap_proxy)
1126 len += eap_proxy_sm_get_status(sm->eap_proxy,
1127 buf + len, buflen - len,
1130 #endif /* CONFIG_EAP_PROXY */
1131 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1138 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1139 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1140 * @buf: Buffer for MIB information
1141 * @buflen: Maximum buffer length
1142 * Returns: Number of bytes written to buf.
1144 * Query EAPOL state machine for MIB information. This function fills in a
1145 * text area with current MIB information from the EAPOL state machine. If
1146 * the buffer (buf) is not large enough, MIB information will be truncated to
1149 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1156 ret = os_snprintf(buf, buflen,
1157 "dot1xSuppPaeState=%d\n"
1158 "dot1xSuppHeldPeriod=%u\n"
1159 "dot1xSuppAuthPeriod=%u\n"
1160 "dot1xSuppStartPeriod=%u\n"
1161 "dot1xSuppMaxStart=%u\n"
1162 "dot1xSuppSuppControlledPortStatus=%s\n"
1163 "dot1xSuppBackendPaeState=%d\n",
1169 sm->suppPortStatus == Authorized ?
1170 "Authorized" : "Unauthorized",
1173 if (ret < 0 || (size_t) ret >= buflen)
1177 ret = os_snprintf(buf + len, buflen - len,
1178 "dot1xSuppEapolFramesRx=%u\n"
1179 "dot1xSuppEapolFramesTx=%u\n"
1180 "dot1xSuppEapolStartFramesTx=%u\n"
1181 "dot1xSuppEapolLogoffFramesTx=%u\n"
1182 "dot1xSuppEapolRespFramesTx=%u\n"
1183 "dot1xSuppEapolReqIdFramesRx=%u\n"
1184 "dot1xSuppEapolReqFramesRx=%u\n"
1185 "dot1xSuppInvalidEapolFramesRx=%u\n"
1186 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1187 "dot1xSuppLastEapolFrameVersion=%u\n"
1188 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1189 sm->dot1xSuppEapolFramesRx,
1190 sm->dot1xSuppEapolFramesTx,
1191 sm->dot1xSuppEapolStartFramesTx,
1192 sm->dot1xSuppEapolLogoffFramesTx,
1193 sm->dot1xSuppEapolRespFramesTx,
1194 sm->dot1xSuppEapolReqIdFramesRx,
1195 sm->dot1xSuppEapolReqFramesRx,
1196 sm->dot1xSuppInvalidEapolFramesRx,
1197 sm->dot1xSuppEapLengthErrorFramesRx,
1198 sm->dot1xSuppLastEapolFrameVersion,
1199 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1201 if (ret < 0 || (size_t) ret >= buflen - len)
1207 #endif /* CONFIG_CTRL_IFACE */
1211 * eapol_sm_rx_eapol - Process received EAPOL frames
1212 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1213 * @src: Source MAC address of the EAPOL packet
1214 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1215 * @len: Length of the EAPOL frame
1216 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1219 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1222 const struct ieee802_1x_hdr *hdr;
1223 const struct ieee802_1x_eapol_key *key;
1230 sm->dot1xSuppEapolFramesRx++;
1231 if (len < sizeof(*hdr)) {
1232 sm->dot1xSuppInvalidEapolFramesRx++;
1235 hdr = (const struct ieee802_1x_hdr *) buf;
1236 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1237 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1238 if (hdr->version < EAPOL_VERSION) {
1239 /* TODO: backwards compatibility */
1241 plen = be_to_host16(hdr->length);
1242 if (plen > len - sizeof(*hdr)) {
1243 sm->dot1xSuppEapLengthErrorFramesRx++;
1247 if (sm->conf.wps && sm->conf.workaround &&
1248 plen < len - sizeof(*hdr) &&
1249 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1250 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1251 const struct eap_hdr *ehdr =
1252 (const struct eap_hdr *) (hdr + 1);
1255 elen = be_to_host16(ehdr->length);
1256 if (elen > plen && elen <= len - sizeof(*hdr)) {
1258 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1259 * packets with too short EAPOL header length field
1260 * (14 octets). This is fixed in firmware Ver.1.49.
1261 * As a workaround, fix the EAPOL header based on the
1262 * correct length in the EAP packet.
1264 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1265 "payload length based on EAP header: "
1266 "%d -> %d", (int) plen, elen);
1270 #endif /* CONFIG_WPS */
1271 data_len = plen + sizeof(*hdr);
1273 switch (hdr->type) {
1274 case IEEE802_1X_TYPE_EAP_PACKET:
1275 if (sm->conf.workaround) {
1277 * An AP has been reported to send out EAP message with
1278 * undocumented code 10 at some point near the
1279 * completion of EAP authentication. This can result in
1280 * issues with the unexpected EAP message triggering
1281 * restart of EAPOL authentication. Avoid this by
1282 * skipping the message without advancing the state
1285 const struct eap_hdr *ehdr =
1286 (const struct eap_hdr *) (hdr + 1);
1287 if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1288 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1293 if (sm->cached_pmk) {
1294 /* Trying to use PMKSA caching, but Authenticator did
1295 * not seem to have a matching entry. Need to restart
1296 * EAPOL state machines.
1298 eapol_sm_abort_cached(sm);
1300 wpabuf_free(sm->eapReqData);
1301 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1302 if (sm->eapReqData) {
1303 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1305 sm->eapolEap = TRUE;
1306 #ifdef CONFIG_EAP_PROXY
1307 if (sm->use_eap_proxy) {
1308 eap_proxy_packet_update(
1310 wpabuf_mhead_u8(sm->eapReqData),
1311 wpabuf_len(sm->eapReqData));
1312 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1315 #endif /* CONFIG_EAP_PROXY */
1319 case IEEE802_1X_TYPE_EAPOL_KEY:
1320 if (plen < sizeof(*key)) {
1321 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1325 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1326 if (key->type == EAPOL_KEY_TYPE_WPA ||
1327 key->type == EAPOL_KEY_TYPE_RSN) {
1328 /* WPA Supplicant takes care of this frame. */
1329 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1330 "frame in EAPOL state machines");
1334 if (key->type != EAPOL_KEY_TYPE_RC4) {
1335 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1336 "EAPOL-Key type %d", key->type);
1339 os_free(sm->last_rx_key);
1340 sm->last_rx_key = os_malloc(data_len);
1341 if (sm->last_rx_key) {
1342 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1344 os_memcpy(sm->last_rx_key, buf, data_len);
1345 sm->last_rx_key_len = data_len;
1350 #ifdef CONFIG_MACSEC
1351 case IEEE802_1X_TYPE_EAPOL_MKA:
1352 wpa_printf(MSG_EXCESSIVE,
1353 "EAPOL type %d will be handled by MKA",
1356 #endif /* CONFIG_MACSEC */
1358 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1360 sm->dot1xSuppInvalidEapolFramesRx++;
1369 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1370 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1372 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1373 * component, e.g., WPA. This will update the statistics.
1375 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1378 sm->dot1xSuppEapolFramesTx++;
1383 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1384 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1385 * @enabled: New portEnabled value
1387 * Notify EAPOL state machine about new portEnabled value.
1389 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1393 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1394 "portEnabled=%d", enabled);
1395 if (sm->portEnabled != enabled)
1396 sm->force_authorized_update = TRUE;
1397 sm->portEnabled = enabled;
1403 * eapol_sm_notify_portValid - Notification about portValid change
1404 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1405 * @valid: New portValid value
1407 * Notify EAPOL state machine about new portValid value.
1409 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1413 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1414 "portValid=%d", valid);
1415 sm->portValid = valid;
1421 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1422 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1423 * @success: %TRUE = set success, %FALSE = clear success
1425 * Notify the EAPOL state machine that external event has forced EAP state to
1426 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1428 * This function is called to update EAP state when WPA-PSK key handshake has
1429 * been completed successfully since WPA-PSK does not use EAP state machine.
1431 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1435 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1436 "EAP success=%d", success);
1437 sm->eapSuccess = success;
1438 sm->altAccept = success;
1440 eap_notify_success(sm->eap);
1446 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1447 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1448 * @fail: %TRUE = set failure, %FALSE = clear failure
1450 * Notify EAPOL state machine that external event has forced EAP state to
1451 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1453 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1457 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1458 "EAP fail=%d", fail);
1460 sm->altReject = fail;
1466 * eapol_sm_notify_config - Notification of EAPOL configuration change
1467 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1468 * @config: Pointer to current network EAP configuration
1469 * @conf: Pointer to EAPOL configuration data
1471 * Notify EAPOL state machine that configuration has changed. config will be
1472 * stored as a backpointer to network configuration. This can be %NULL to clear
1473 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1474 * data. If conf is %NULL, this part of the configuration change will be
1477 void eapol_sm_notify_config(struct eapol_sm *sm,
1478 struct eap_peer_config *config,
1479 const struct eapol_config *conf)
1484 sm->config = config;
1485 #ifdef CONFIG_EAP_PROXY
1486 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1487 #endif /* CONFIG_EAP_PROXY */
1492 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1493 sm->conf.required_keys = conf->required_keys;
1494 sm->conf.fast_reauth = conf->fast_reauth;
1495 sm->conf.workaround = conf->workaround;
1496 sm->conf.wps = conf->wps;
1497 #ifdef CONFIG_EAP_PROXY
1498 if (sm->use_eap_proxy) {
1499 /* Using EAP Proxy, so skip EAP state machine update */
1502 #endif /* CONFIG_EAP_PROXY */
1504 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1505 eap_set_workaround(sm->eap, conf->workaround);
1506 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1507 eap_set_external_sim(sm->eap, conf->external_sim);
1513 * eapol_sm_get_key - Get master session key (MSK) from EAP
1514 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1515 * @key: Pointer for key buffer
1516 * @len: Number of bytes to copy to key
1517 * Returns: 0 on success (len of key available), maximum available key len
1518 * (>0) if key is available but it is shorter than len, or -1 on failure.
1520 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1521 * is available only after a successful authentication.
1523 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1528 #ifdef CONFIG_EAP_PROXY
1529 if (sm && sm->use_eap_proxy) {
1530 /* Get key from EAP proxy */
1531 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1532 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1535 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1536 if (eap_key == NULL) {
1537 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1543 #endif /* CONFIG_EAP_PROXY */
1544 if (sm == NULL || !eap_key_available(sm->eap)) {
1545 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1548 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1549 if (eap_key == NULL) {
1550 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1553 #ifdef CONFIG_EAP_PROXY
1555 #endif /* CONFIG_EAP_PROXY */
1556 if (len > eap_len) {
1557 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1558 "available (len=%lu)",
1559 (unsigned long) len, (unsigned long) eap_len);
1562 os_memcpy(key, eap_key, len);
1563 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1564 (unsigned long) len);
1570 * eapol_sm_get_session_id - Get EAP Session-Id
1571 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1572 * @len: Pointer to variable that will be set to number of bytes in the session
1573 * Returns: Pointer to the EAP Session-Id or %NULL on failure
1575 * The Session-Id is available only after a successful authentication.
1577 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
1579 if (sm == NULL || !eap_key_available(sm->eap)) {
1580 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
1583 return eap_get_eapSessionId(sm->eap, len);
1588 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1589 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1590 * @logoff: Whether command was logoff
1592 * Notify EAPOL state machines that user requested logon/logoff.
1594 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1597 sm->userLogoff = logoff;
1599 /* If there is a delayed txStart queued, start now. */
1608 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1609 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1611 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1612 * to move EAPOL and EAP state machines into authenticated/successful state.
1614 void eapol_sm_notify_cached(struct eapol_sm *sm)
1618 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1619 sm->eapSuccess = TRUE;
1620 eap_notify_success(sm->eap);
1626 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1627 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1628 * @attempt: Whether PMKSA caching is tried
1630 * Notify EAPOL state machines whether PMKSA caching is used.
1632 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
1637 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1638 sm->cached_pmk = TRUE;
1640 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
1641 sm->cached_pmk = FALSE;
1646 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1648 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1649 "doing full EAP authentication");
1652 sm->cached_pmk = FALSE;
1653 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1654 eapol_sm_set_port_unauthorized(sm);
1656 /* Make sure we do not start sending EAPOL-Start frames first, but
1657 * instead move to RESTART state to start EAPOL authentication. */
1659 eapol_enable_timer_tick(sm);
1661 if (sm->ctx->aborted_cached)
1662 sm->ctx->aborted_cached(sm->ctx->ctx);
1667 * eapol_sm_register_scard_ctx - Notification of smart card context
1668 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1669 * @ctx: Context data for smart card operations
1671 * Notify EAPOL state machines of context data for smart card operations. This
1672 * context data will be used as a parameter for scard_*() functions.
1674 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1677 sm->ctx->scard_ctx = ctx;
1678 eap_register_scard_ctx(sm->eap, ctx);
1684 * eapol_sm_notify_portControl - Notification of portControl changes
1685 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1686 * @portControl: New value for portControl variable
1688 * Notify EAPOL state machines that portControl variable has changed.
1690 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1694 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1695 "portControl=%s", eapol_port_control(portControl));
1696 sm->portControl = portControl;
1702 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1703 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1705 * Notify EAPOL state machines that a monitor was attached to the control
1706 * interface to trigger re-sending of pending requests for user input.
1708 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1712 eap_sm_notify_ctrl_attached(sm->eap);
1717 * eapol_sm_notify_ctrl_response - Notification of received user input
1718 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1720 * Notify EAPOL state machines that a control response, i.e., user
1721 * input, was received in order to trigger retrying of a pending EAP request.
1723 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1727 if (sm->eapReqData && !sm->eapReq) {
1728 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1729 "input) notification - retrying pending EAP "
1731 sm->eapolEap = TRUE;
1739 * eapol_sm_request_reauth - Request reauthentication
1740 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1742 * This function can be used to request EAPOL reauthentication, e.g., when the
1743 * current PMKSA entry is nearing expiration.
1745 void eapol_sm_request_reauth(struct eapol_sm *sm)
1747 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1749 eapol_sm_txStart(sm);
1754 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1755 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1756 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1757 * machine loop (eapol_sm_step())
1759 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1760 * successful authentication. This is used to recover from dropped EAP-Success
1763 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1767 eap_notify_lower_layer_success(sm->eap);
1774 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1775 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1777 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1780 eap_invalidate_cached_session(sm->eap);
1784 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1786 struct eapol_sm *sm = ctx;
1787 return sm ? sm->config : NULL;
1791 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1793 struct eapol_sm *sm = ctx;
1794 if (sm == NULL || sm->eapReqData == NULL)
1797 return sm->eapReqData;
1801 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1803 struct eapol_sm *sm = ctx;
1807 case EAPOL_eapSuccess:
1808 return sm->eapSuccess;
1809 case EAPOL_eapRestart:
1810 return sm->eapRestart;
1815 case EAPOL_eapNoResp:
1816 return sm->eapNoResp;
1819 case EAPOL_portEnabled:
1820 return sm->portEnabled;
1821 case EAPOL_altAccept:
1822 return sm->altAccept;
1823 case EAPOL_altReject:
1824 return sm->altReject;
1830 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1833 struct eapol_sm *sm = ctx;
1837 case EAPOL_eapSuccess:
1838 sm->eapSuccess = value;
1840 case EAPOL_eapRestart:
1841 sm->eapRestart = value;
1844 sm->eapFail = value;
1847 sm->eapResp = value;
1849 case EAPOL_eapNoResp:
1850 sm->eapNoResp = value;
1855 case EAPOL_portEnabled:
1856 sm->portEnabled = value;
1858 case EAPOL_altAccept:
1859 sm->altAccept = value;
1861 case EAPOL_altReject:
1862 sm->altReject = value;
1868 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1870 struct eapol_sm *sm = ctx;
1874 case EAPOL_idleWhile:
1875 return sm->idleWhile;
1881 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1884 struct eapol_sm *sm = ctx;
1888 case EAPOL_idleWhile:
1889 sm->idleWhile = value;
1890 if (sm->idleWhile > 0)
1891 eapol_enable_timer_tick(sm);
1897 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1899 #ifndef CONFIG_NO_CONFIG_BLOBS
1900 struct eapol_sm *sm = ctx;
1901 if (sm && sm->ctx && sm->ctx->set_config_blob)
1902 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1903 #endif /* CONFIG_NO_CONFIG_BLOBS */
1907 static const struct wpa_config_blob *
1908 eapol_sm_get_config_blob(void *ctx, const char *name)
1910 #ifndef CONFIG_NO_CONFIG_BLOBS
1911 struct eapol_sm *sm = ctx;
1912 if (sm && sm->ctx && sm->ctx->get_config_blob)
1913 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1916 #else /* CONFIG_NO_CONFIG_BLOBS */
1918 #endif /* CONFIG_NO_CONFIG_BLOBS */
1922 static void eapol_sm_notify_pending(void *ctx)
1924 struct eapol_sm *sm = ctx;
1927 if (sm->eapReqData && !sm->eapReq) {
1928 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1929 "state machine - retrying pending EAP Request");
1930 sm->eapolEap = TRUE;
1937 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1938 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1941 struct eapol_sm *sm = ctx;
1942 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1943 if (sm->ctx->eap_param_needed)
1944 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1946 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1947 #define eapol_sm_eap_param_needed NULL
1948 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1950 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
1951 const char *cert_hash,
1952 const struct wpabuf *cert)
1954 struct eapol_sm *sm = ctx;
1955 if (sm->ctx->cert_cb)
1956 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
1961 static void eapol_sm_notify_status(void *ctx, const char *status,
1962 const char *parameter)
1964 struct eapol_sm *sm = ctx;
1966 if (sm->ctx->status_cb)
1967 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
1971 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
1973 struct eapol_sm *sm = ctx;
1975 if (sm->ctx->set_anon_id)
1976 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
1980 static struct eapol_callbacks eapol_cb =
1982 eapol_sm_get_config,
1987 eapol_sm_get_eapReqData,
1988 eapol_sm_set_config_blob,
1989 eapol_sm_get_config_blob,
1990 eapol_sm_notify_pending,
1991 eapol_sm_eap_param_needed,
1992 eapol_sm_notify_cert,
1993 eapol_sm_notify_status,
1994 eapol_sm_set_anon_id
1999 * eapol_sm_init - Initialize EAPOL state machine
2000 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2001 * and EAPOL state machine will free it in eapol_sm_deinit()
2002 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2004 * Allocate and initialize an EAPOL state machine.
2006 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
2008 struct eapol_sm *sm;
2009 struct eap_config conf;
2010 sm = os_zalloc(sizeof(*sm));
2015 sm->portControl = Auto;
2017 /* Supplicant PAE state machine */
2018 sm->heldPeriod = 60;
2019 sm->startPeriod = 30;
2022 /* Supplicant Backend state machine */
2023 sm->authPeriod = 30;
2025 os_memset(&conf, 0, sizeof(conf));
2026 conf.opensc_engine_path = ctx->opensc_engine_path;
2027 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2028 conf.pkcs11_module_path = ctx->pkcs11_module_path;
2029 conf.openssl_ciphers = ctx->openssl_ciphers;
2030 conf.wps = ctx->wps;
2031 conf.cert_in_cb = ctx->cert_in_cb;
2033 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2034 if (sm->eap == NULL) {
2039 #ifdef CONFIG_EAP_PROXY
2040 sm->use_eap_proxy = FALSE;
2041 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2042 if (sm->eap_proxy == NULL) {
2043 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2045 #endif /* CONFIG_EAP_PROXY */
2047 /* Initialize EAPOL state machines */
2048 sm->force_authorized_update = TRUE;
2049 sm->initialize = TRUE;
2051 sm->initialize = FALSE;
2054 sm->timer_tick_enabled = 1;
2055 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2062 * eapol_sm_deinit - Deinitialize EAPOL state machine
2063 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2065 * Deinitialize and free EAPOL state machine.
2067 void eapol_sm_deinit(struct eapol_sm *sm)
2071 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2072 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2073 eap_peer_sm_deinit(sm->eap);
2074 #ifdef CONFIG_EAP_PROXY
2075 eap_proxy_deinit(sm->eap_proxy);
2076 #endif /* CONFIG_EAP_PROXY */
2077 os_free(sm->last_rx_key);
2078 wpabuf_free(sm->eapReqData);
2084 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2085 struct ext_password_data *ext)
2088 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2092 int eapol_sm_failed(struct eapol_sm *sm)
2096 return !sm->eapSuccess && sm->eapFail;
2100 int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
2102 #ifdef CONFIG_EAP_PROXY
2103 if (sm->eap_proxy == NULL)
2105 return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
2106 #else /* CONFIG_EAP_PROXY */
2108 #endif /* CONFIG_EAP_PROXY */