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 eapTriggerStart;
132 Boolean replay_counter_valid;
133 u8 last_replay_counter[16];
134 struct eapol_config conf;
135 struct eapol_ctx *ctx;
136 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
140 Boolean unicast_key_received, broadcast_key_received;
142 Boolean force_authorized_update;
144 #ifdef CONFIG_EAP_PROXY
145 Boolean use_eap_proxy;
146 struct eap_proxy_sm *eap_proxy;
147 #endif /* CONFIG_EAP_PROXY */
151 static void eapol_sm_txLogoff(struct eapol_sm *sm);
152 static void eapol_sm_txStart(struct eapol_sm *sm);
153 static void eapol_sm_processKey(struct eapol_sm *sm);
154 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
155 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
156 static void eapol_sm_abortSupp(struct eapol_sm *sm);
157 static void eapol_sm_abort_cached(struct eapol_sm *sm);
158 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
159 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
160 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
163 /* Port Timers state machine - implemented as a function that will be called
164 * once a second as a registered event loop timeout */
165 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
167 struct eapol_sm *sm = timeout_ctx;
169 if (sm->authWhile > 0) {
171 if (sm->authWhile == 0)
172 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
174 if (sm->heldWhile > 0) {
176 if (sm->heldWhile == 0)
177 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
179 if (sm->startWhen > 0) {
181 if (sm->startWhen == 0)
182 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
184 if (sm->idleWhile > 0) {
186 if (sm->idleWhile == 0)
187 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
190 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
191 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
194 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
195 sm->timer_tick_enabled = 0;
201 static void eapol_enable_timer_tick(struct eapol_sm *sm)
203 if (sm->timer_tick_enabled)
205 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
206 sm->timer_tick_enabled = 1;
207 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
208 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
212 SM_STATE(SUPP_PAE, LOGOFF)
214 SM_ENTRY(SUPP_PAE, LOGOFF);
215 eapol_sm_txLogoff(sm);
216 sm->logoffSent = TRUE;
217 eapol_sm_set_port_unauthorized(sm);
221 SM_STATE(SUPP_PAE, DISCONNECTED)
223 SM_ENTRY(SUPP_PAE, DISCONNECTED);
224 sm->sPortMode = Auto;
226 sm->eapTriggerStart = FALSE;
227 sm->logoffSent = FALSE;
228 eapol_sm_set_port_unauthorized(sm);
229 sm->suppAbort = TRUE;
231 sm->unicast_key_received = FALSE;
232 sm->broadcast_key_received = FALSE;
235 * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
236 * allows the timer tick to be stopped more quickly when the port is
237 * not enabled. Since this variable is used only within HELD state,
238 * clearing it on initialization does not change actual state machine
245 SM_STATE(SUPP_PAE, CONNECTING)
247 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
248 sm->SUPP_PAE_state == SUPP_PAE_HELD;
249 SM_ENTRY(SUPP_PAE, CONNECTING);
251 if (sm->eapTriggerStart)
253 sm->eapTriggerStart = FALSE;
256 sm->startWhen = sm->startPeriod;
260 * Do not send EAPOL-Start immediately since in most cases,
261 * Authenticator is going to start authentication immediately
262 * after association and an extra EAPOL-Start is just going to
263 * delay authentication. Use a short timeout to send the first
264 * EAPOL-Start if Authenticator does not start authentication.
266 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
267 /* Reduce latency on starting WPS negotiation. */
268 wpa_printf(MSG_DEBUG,
269 "EAPOL: Using shorter startWhen for WPS");
275 eapol_enable_timer_tick(sm);
276 sm->eapolEap = FALSE;
278 eapol_sm_txStart(sm);
282 SM_STATE(SUPP_PAE, AUTHENTICATING)
284 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
286 sm->suppSuccess = FALSE;
287 sm->suppFail = FALSE;
288 sm->suppTimeout = FALSE;
291 sm->suppStart = TRUE;
295 SM_STATE(SUPP_PAE, HELD)
297 SM_ENTRY(SUPP_PAE, HELD);
298 sm->heldWhile = sm->heldPeriod;
299 eapol_enable_timer_tick(sm);
300 eapol_sm_set_port_unauthorized(sm);
301 sm->cb_status = EAPOL_CB_FAILURE;
305 SM_STATE(SUPP_PAE, AUTHENTICATED)
307 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
308 eapol_sm_set_port_authorized(sm);
309 sm->cb_status = EAPOL_CB_SUCCESS;
313 SM_STATE(SUPP_PAE, RESTART)
315 SM_ENTRY(SUPP_PAE, RESTART);
316 sm->eapRestart = TRUE;
319 * Prevent EAP peer state machine from failing due to prior
320 * external EAP success notification (altSuccess=TRUE in the
321 * IDLE state could result in a transition to the FAILURE state.
323 wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
324 sm->eapSuccess = FALSE;
325 sm->altAccept = FALSE;
330 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
332 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
333 eapol_sm_set_port_authorized(sm);
334 sm->sPortMode = ForceAuthorized;
338 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
340 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
341 eapol_sm_set_port_unauthorized(sm);
342 sm->sPortMode = ForceUnauthorized;
343 eapol_sm_txLogoff(sm);
349 if ((sm->userLogoff && !sm->logoffSent) &&
350 !(sm->initialize || !sm->portEnabled))
351 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
352 else if (((sm->portControl == Auto) &&
353 (sm->sPortMode != sm->portControl)) ||
354 sm->initialize || !sm->portEnabled)
355 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
356 else if ((sm->portControl == ForceAuthorized) &&
357 (sm->sPortMode != sm->portControl) &&
358 !(sm->initialize || !sm->portEnabled))
359 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
360 else if ((sm->portControl == ForceUnauthorized) &&
361 (sm->sPortMode != sm->portControl) &&
362 !(sm->initialize || !sm->portEnabled))
363 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
364 else switch (sm->SUPP_PAE_state) {
365 case SUPP_PAE_UNKNOWN:
367 case SUPP_PAE_LOGOFF:
369 SM_ENTER(SUPP_PAE, DISCONNECTED);
371 case SUPP_PAE_DISCONNECTED:
372 SM_ENTER(SUPP_PAE, CONNECTING);
374 case SUPP_PAE_CONNECTING:
375 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
376 SM_ENTER(SUPP_PAE, CONNECTING);
377 else if (sm->startWhen == 0 &&
378 sm->startCount >= sm->maxStart &&
380 SM_ENTER(SUPP_PAE, AUTHENTICATED);
381 else if (sm->eapSuccess || sm->eapFail)
382 SM_ENTER(SUPP_PAE, AUTHENTICATING);
383 else if (sm->eapolEap)
384 SM_ENTER(SUPP_PAE, RESTART);
385 else if (sm->startWhen == 0 &&
386 sm->startCount >= sm->maxStart &&
388 SM_ENTER(SUPP_PAE, HELD);
390 case SUPP_PAE_AUTHENTICATING:
391 if (sm->eapSuccess && !sm->portValid &&
392 sm->conf.accept_802_1x_keys &&
393 sm->conf.required_keys == 0) {
394 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
395 "plaintext connection; no EAPOL-Key frames "
397 sm->portValid = TRUE;
398 if (sm->ctx->eapol_done_cb)
399 sm->ctx->eapol_done_cb(sm->ctx->ctx);
401 if (sm->eapSuccess && sm->portValid)
402 SM_ENTER(SUPP_PAE, AUTHENTICATED);
403 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
404 SM_ENTER(SUPP_PAE, HELD);
405 else if (sm->suppTimeout)
406 SM_ENTER(SUPP_PAE, CONNECTING);
407 else if (sm->eapTriggerStart)
408 SM_ENTER(SUPP_PAE, CONNECTING);
411 if (sm->heldWhile == 0)
412 SM_ENTER(SUPP_PAE, CONNECTING);
413 else if (sm->eapolEap)
414 SM_ENTER(SUPP_PAE, RESTART);
416 case SUPP_PAE_AUTHENTICATED:
417 if (sm->eapolEap && sm->portValid)
418 SM_ENTER(SUPP_PAE, RESTART);
419 else if (!sm->portValid)
420 SM_ENTER(SUPP_PAE, DISCONNECTED);
422 case SUPP_PAE_RESTART:
424 SM_ENTER(SUPP_PAE, AUTHENTICATING);
426 case SUPP_PAE_S_FORCE_AUTH:
428 case SUPP_PAE_S_FORCE_UNAUTH:
434 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
436 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
440 SM_STATE(KEY_RX, KEY_RECEIVE)
442 SM_ENTRY(KEY_RX, KEY_RECEIVE);
443 eapol_sm_processKey(sm);
450 if (sm->initialize || !sm->portEnabled)
451 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
452 switch (sm->KEY_RX_state) {
455 case KEY_RX_NO_KEY_RECEIVE:
457 SM_ENTER(KEY_RX, KEY_RECEIVE);
459 case KEY_RX_KEY_RECEIVE:
461 SM_ENTER(KEY_RX, KEY_RECEIVE);
467 SM_STATE(SUPP_BE, REQUEST)
469 SM_ENTRY(SUPP_BE, REQUEST);
472 eapol_sm_getSuppRsp(sm);
476 SM_STATE(SUPP_BE, RESPONSE)
478 SM_ENTRY(SUPP_BE, RESPONSE);
479 eapol_sm_txSuppRsp(sm);
484 SM_STATE(SUPP_BE, SUCCESS)
486 SM_ENTRY(SUPP_BE, SUCCESS);
488 sm->suppSuccess = TRUE;
490 #ifdef CONFIG_EAP_PROXY
491 if (sm->use_eap_proxy) {
492 if (eap_proxy_key_available(sm->eap_proxy)) {
493 /* New key received - clear IEEE 802.1X EAPOL-Key replay
495 sm->replay_counter_valid = FALSE;
499 #endif /* CONFIG_EAP_PROXY */
501 if (eap_key_available(sm->eap)) {
502 /* New key received - clear IEEE 802.1X EAPOL-Key replay
504 sm->replay_counter_valid = FALSE;
509 SM_STATE(SUPP_BE, FAIL)
511 SM_ENTRY(SUPP_BE, FAIL);
516 SM_STATE(SUPP_BE, TIMEOUT)
518 SM_ENTRY(SUPP_BE, TIMEOUT);
519 sm->suppTimeout = TRUE;
523 SM_STATE(SUPP_BE, IDLE)
525 SM_ENTRY(SUPP_BE, IDLE);
526 sm->suppStart = FALSE;
527 sm->initial_req = TRUE;
531 SM_STATE(SUPP_BE, INITIALIZE)
533 SM_ENTRY(SUPP_BE, INITIALIZE);
534 eapol_sm_abortSupp(sm);
535 sm->suppAbort = FALSE;
538 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
539 * allows the timer tick to be stopped more quickly when the port is
540 * not enabled. Since this variable is used only within RECEIVE state,
541 * clearing it on initialization does not change actual state machine
548 SM_STATE(SUPP_BE, RECEIVE)
550 SM_ENTRY(SUPP_BE, RECEIVE);
551 sm->authWhile = sm->authPeriod;
552 eapol_enable_timer_tick(sm);
553 sm->eapolEap = FALSE;
554 sm->eapNoResp = FALSE;
555 sm->initial_req = FALSE;
561 if (sm->initialize || sm->suppAbort)
562 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
563 else switch (sm->SUPP_BE_state) {
564 case SUPP_BE_UNKNOWN:
566 case SUPP_BE_REQUEST:
568 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
569 * and SUCCESS based on eapFail and eapSuccess, respectively.
570 * However, IEEE Std 802.1X-2004 is also specifying that
571 * eapNoResp should be set in conjunction with eapSuccess and
572 * eapFail which would mean that more than one of the
573 * transitions here would be activated at the same time.
574 * Skipping RESPONSE and/or RECEIVE states in these cases can
575 * cause problems and the direct transitions to do not seem
576 * correct. Because of this, the conditions for these
577 * transitions are verified only after eapNoResp. They are
578 * unlikely to be used since eapNoResp should always be set if
579 * either of eapSuccess or eapFail is set.
581 if (sm->eapResp && sm->eapNoResp) {
582 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
583 "eapResp and eapNoResp set?!");
586 SM_ENTER(SUPP_BE, RESPONSE);
587 else if (sm->eapNoResp)
588 SM_ENTER(SUPP_BE, RECEIVE);
589 else if (sm->eapFail)
590 SM_ENTER(SUPP_BE, FAIL);
591 else if (sm->eapSuccess)
592 SM_ENTER(SUPP_BE, SUCCESS);
594 case SUPP_BE_RESPONSE:
595 SM_ENTER(SUPP_BE, RECEIVE);
597 case SUPP_BE_SUCCESS:
598 SM_ENTER(SUPP_BE, IDLE);
601 SM_ENTER(SUPP_BE, IDLE);
603 case SUPP_BE_TIMEOUT:
604 SM_ENTER(SUPP_BE, IDLE);
607 if (sm->eapFail && sm->suppStart)
608 SM_ENTER(SUPP_BE, FAIL);
609 else if (sm->eapolEap && sm->suppStart)
610 SM_ENTER(SUPP_BE, REQUEST);
611 else if (sm->eapSuccess && sm->suppStart)
612 SM_ENTER(SUPP_BE, SUCCESS);
614 case SUPP_BE_INITIALIZE:
615 SM_ENTER(SUPP_BE, IDLE);
617 case SUPP_BE_RECEIVE:
619 SM_ENTER(SUPP_BE, REQUEST);
620 else if (sm->eapFail)
621 SM_ENTER(SUPP_BE, FAIL);
622 else if (sm->authWhile == 0)
623 SM_ENTER(SUPP_BE, TIMEOUT);
624 else if (sm->eapSuccess)
625 SM_ENTER(SUPP_BE, SUCCESS);
631 static void eapol_sm_txLogoff(struct eapol_sm *sm)
633 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
634 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
635 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
636 sm->dot1xSuppEapolLogoffFramesTx++;
637 sm->dot1xSuppEapolFramesTx++;
641 static void eapol_sm_txStart(struct eapol_sm *sm)
643 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
644 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
645 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
646 sm->dot1xSuppEapolStartFramesTx++;
647 sm->dot1xSuppEapolFramesTx++;
651 #define IEEE8021X_ENCR_KEY_LEN 32
652 #define IEEE8021X_SIGN_KEY_LEN 32
654 struct eap_key_data {
655 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
656 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
660 static void eapol_sm_processKey(struct eapol_sm *sm)
663 struct ieee802_1x_hdr *hdr;
664 struct ieee802_1x_eapol_key *key;
665 struct eap_key_data keydata;
666 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
667 #ifndef CONFIG_NO_RC4
668 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
669 #endif /* CONFIG_NO_RC4 */
670 int key_len, res, sign_key_len, encr_key_len;
674 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
675 if (sm->last_rx_key == NULL)
678 if (!sm->conf.accept_802_1x_keys) {
679 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
680 " even though this was not accepted - "
681 "ignoring this packet");
685 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
687 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
688 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
689 plen = be_to_host16(hdr->length);
690 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
691 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
694 rx_key_length = WPA_GET_BE16(key->key_length);
695 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
696 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
697 hdr->version, hdr->type, be_to_host16(hdr->length),
698 key->type, rx_key_length, key->key_index);
700 eapol_sm_notify_lower_layer_success(sm, 1);
701 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
702 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
703 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
705 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
706 "decrypting EAPOL-Key keys");
710 /* LEAP derives only 16 bytes of keying material. */
711 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
713 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
714 "master key for decrypting EAPOL-Key keys");
719 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
721 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
722 "data for decrypting EAPOL-Key keys (res=%d)", res);
726 /* The key replay_counter must increase when same master key */
727 if (sm->replay_counter_valid &&
728 os_memcmp(sm->last_replay_counter, key->replay_counter,
729 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
730 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
731 "not increase - ignoring key");
732 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
733 sm->last_replay_counter,
734 IEEE8021X_REPLAY_COUNTER_LEN);
735 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
736 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
740 /* Verify key signature (HMAC-MD5) */
741 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
742 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
743 hmac_md5(keydata.sign_key, sign_key_len,
744 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
746 if (os_memcmp_const(orig_key_sign, key->key_signature,
747 IEEE8021X_KEY_SIGN_LEN) != 0) {
748 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
750 os_memcpy(key->key_signature, orig_key_sign,
751 IEEE8021X_KEY_SIGN_LEN);
754 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
756 key_len = plen - sizeof(*key);
757 if (key_len > 32 || rx_key_length > 32) {
758 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
759 key_len ? key_len : rx_key_length);
762 if (key_len == rx_key_length) {
765 /* otherwise unused */
767 wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build");
769 #else /* CONFIG_NO_RC4 */
770 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
771 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
773 os_memcpy(datakey, key + 1, key_len);
774 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
776 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
778 #endif /* CONFIG_NO_RC4 */
779 } else if (key_len == 0) {
781 * IEEE 802.1X-2004 specifies that least significant Key Length
782 * octets from MS-MPPE-Send-Key are used as the key if the key
783 * data is not present. This seems to be meaning the beginning
784 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
785 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
786 * Anyway, taking the beginning of the keying material from EAP
787 * seems to interoperate with Authenticators.
789 key_len = rx_key_length;
790 os_memcpy(datakey, keydata.encr_key, key_len);
791 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
792 "material data encryption key",
795 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
796 "(key_length=%d)", key_len, rx_key_length);
800 sm->replay_counter_valid = TRUE;
801 os_memcpy(sm->last_replay_counter, key->replay_counter,
802 IEEE8021X_REPLAY_COUNTER_LEN);
804 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
806 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
807 "unicast" : "broadcast",
808 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
810 if (sm->ctx->set_wep_key &&
811 sm->ctx->set_wep_key(sm->ctx->ctx,
812 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
813 key->key_index & IEEE8021X_KEY_INDEX_MASK,
814 datakey, key_len) < 0) {
815 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
818 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
819 sm->unicast_key_received = TRUE;
821 sm->broadcast_key_received = TRUE;
823 if ((sm->unicast_key_received ||
824 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
825 (sm->broadcast_key_received ||
826 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
828 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
830 sm->portValid = TRUE;
831 if (sm->ctx->eapol_done_cb)
832 sm->ctx->eapol_done_cb(sm->ctx->ctx);
835 #endif /* CONFIG_FIPS */
839 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
841 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
842 /* EAP layer processing; no special code is needed, since Supplicant
843 * Backend state machine is waiting for eapNoResp or eapResp to be set
844 * and these are only set in the EAP state machine when the processing
849 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
853 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
855 #ifdef CONFIG_EAP_PROXY
856 if (sm->use_eap_proxy) {
857 /* Get EAP Response from EAP Proxy */
858 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
860 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
861 "response data not available");
865 #endif /* CONFIG_EAP_PROXY */
867 resp = eap_get_eapRespData(sm->eap);
869 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
874 /* Send EAP-Packet from the EAP layer to the Authenticator */
875 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
876 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
879 /* eapRespData is not used anymore, so free it here */
883 sm->dot1xSuppEapolReqIdFramesRx++;
885 sm->dot1xSuppEapolReqFramesRx++;
886 sm->dot1xSuppEapolRespFramesTx++;
887 sm->dot1xSuppEapolFramesTx++;
891 static void eapol_sm_abortSupp(struct eapol_sm *sm)
893 /* release system resources that may have been allocated for the
894 * authentication session */
895 os_free(sm->last_rx_key);
896 sm->last_rx_key = NULL;
897 wpabuf_free(sm->eapReqData);
898 sm->eapReqData = NULL;
899 eap_sm_abort(sm->eap);
903 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
905 eapol_sm_step(timeout_ctx);
909 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
913 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
914 sm->force_authorized_update = FALSE;
915 sm->suppPortStatus = Authorized;
916 if (cb && sm->ctx->port_cb)
917 sm->ctx->port_cb(sm->ctx->ctx, 1);
921 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
925 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
926 sm->force_authorized_update = FALSE;
927 sm->suppPortStatus = Unauthorized;
928 if (cb && sm->ctx->port_cb)
929 sm->ctx->port_cb(sm->ctx->ctx, 0);
934 * eapol_sm_step - EAPOL state machine step function
935 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
937 * This function is called to notify the state machine about changed external
938 * variables. It will step through the EAPOL state machines in loop to process
939 * all triggered state changes.
941 void eapol_sm_step(struct eapol_sm *sm)
945 /* In theory, it should be ok to run this in loop until !changed.
946 * However, it is better to use a limit on number of iterations to
947 * allow events (e.g., SIGTERM) to stop the program cleanly if the
948 * state machine were to generate a busy loop. */
949 for (i = 0; i < 100; i++) {
951 SM_STEP_RUN(SUPP_PAE);
953 SM_STEP_RUN(SUPP_BE);
954 #ifdef CONFIG_EAP_PROXY
955 if (sm->use_eap_proxy) {
956 /* Drive the EAP proxy state machine */
957 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
960 #endif /* CONFIG_EAP_PROXY */
961 if (eap_peer_sm_step(sm->eap))
968 /* restart EAPOL state machine step from timeout call in order
969 * to allow other events to be processed. */
970 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
971 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
974 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
975 enum eapol_supp_result result;
976 if (sm->cb_status == EAPOL_CB_SUCCESS)
977 result = EAPOL_SUPP_RESULT_SUCCESS;
978 else if (eap_peer_was_failure_expected(sm->eap))
979 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
981 result = EAPOL_SUPP_RESULT_FAILURE;
982 sm->cb_status = EAPOL_CB_IN_PROGRESS;
983 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
988 #ifdef CONFIG_CTRL_IFACE
989 static const char *eapol_supp_pae_state(int state)
992 case SUPP_PAE_LOGOFF:
994 case SUPP_PAE_DISCONNECTED:
995 return "DISCONNECTED";
996 case SUPP_PAE_CONNECTING:
998 case SUPP_PAE_AUTHENTICATING:
999 return "AUTHENTICATING";
1002 case SUPP_PAE_AUTHENTICATED:
1003 return "AUTHENTICATED";
1004 case SUPP_PAE_RESTART:
1012 static const char *eapol_supp_be_state(int state)
1015 case SUPP_BE_REQUEST:
1017 case SUPP_BE_RESPONSE:
1019 case SUPP_BE_SUCCESS:
1023 case SUPP_BE_TIMEOUT:
1027 case SUPP_BE_INITIALIZE:
1028 return "INITIALIZE";
1029 case SUPP_BE_RECEIVE:
1037 static const char * eapol_port_status(PortStatus status)
1039 if (status == Authorized)
1040 return "Authorized";
1042 return "Unauthorized";
1044 #endif /* CONFIG_CTRL_IFACE */
1047 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1048 static const char * eapol_port_control(PortControl ctrl)
1053 case ForceUnauthorized:
1054 return "ForceUnauthorized";
1055 case ForceAuthorized:
1056 return "ForceAuthorized";
1061 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1065 * eapol_sm_configure - Set EAPOL variables
1066 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1067 * @heldPeriod: dot1xSuppHeldPeriod
1068 * @authPeriod: dot1xSuppAuthPeriod
1069 * @startPeriod: dot1xSuppStartPeriod
1070 * @maxStart: dot1xSuppMaxStart
1072 * Set configurable EAPOL state machine variables. Each variable can be set to
1073 * the given value or ignored if set to -1 (to set only some of the variables).
1075 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1076 int startPeriod, int maxStart)
1080 if (heldPeriod >= 0)
1081 sm->heldPeriod = heldPeriod;
1082 if (authPeriod >= 0)
1083 sm->authPeriod = authPeriod;
1084 if (startPeriod >= 0)
1085 sm->startPeriod = startPeriod;
1087 sm->maxStart = maxStart;
1092 * eapol_sm_get_method_name - Get EAPOL method name
1093 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1094 * Returns: Static string containing name of current eap method or NULL
1096 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1098 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1099 sm->suppPortStatus != Authorized)
1102 return eap_sm_get_method_name(sm->eap);
1106 #ifdef CONFIG_CTRL_IFACE
1108 * eapol_sm_get_status - Get EAPOL state machine status
1109 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1110 * @buf: Buffer for status information
1111 * @buflen: Maximum buffer length
1112 * @verbose: Whether to include verbose status information
1113 * Returns: Number of bytes written to buf.
1115 * Query EAPOL state machine for status information. This function fills in a
1116 * text area with current status information from the EAPOL state machine. If
1117 * the buffer (buf) is not large enough, status information will be truncated
1118 * to fit the buffer.
1120 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1127 len = os_snprintf(buf, buflen,
1128 "Supplicant PAE state=%s\n"
1129 "suppPortStatus=%s\n",
1130 eapol_supp_pae_state(sm->SUPP_PAE_state),
1131 eapol_port_status(sm->suppPortStatus));
1132 if (os_snprintf_error(buflen, len))
1136 ret = os_snprintf(buf + len, buflen - len,
1142 "Supplicant Backend state=%s\n",
1147 eapol_port_control(sm->portControl),
1148 eapol_supp_be_state(sm->SUPP_BE_state));
1149 if (os_snprintf_error(buflen - len, ret))
1154 #ifdef CONFIG_EAP_PROXY
1155 if (sm->use_eap_proxy)
1156 len += eap_proxy_sm_get_status(sm->eap_proxy,
1157 buf + len, buflen - len,
1160 #endif /* CONFIG_EAP_PROXY */
1161 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1168 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1169 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1170 * @buf: Buffer for MIB information
1171 * @buflen: Maximum buffer length
1172 * Returns: Number of bytes written to buf.
1174 * Query EAPOL state machine for MIB information. This function fills in a
1175 * text area with current MIB information from the EAPOL state machine. If
1176 * the buffer (buf) is not large enough, MIB information will be truncated to
1179 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1186 ret = os_snprintf(buf, buflen,
1187 "dot1xSuppPaeState=%d\n"
1188 "dot1xSuppHeldPeriod=%u\n"
1189 "dot1xSuppAuthPeriod=%u\n"
1190 "dot1xSuppStartPeriod=%u\n"
1191 "dot1xSuppMaxStart=%u\n"
1192 "dot1xSuppSuppControlledPortStatus=%s\n"
1193 "dot1xSuppBackendPaeState=%d\n",
1199 sm->suppPortStatus == Authorized ?
1200 "Authorized" : "Unauthorized",
1203 if (os_snprintf_error(buflen, ret))
1207 ret = os_snprintf(buf + len, buflen - len,
1208 "dot1xSuppEapolFramesRx=%u\n"
1209 "dot1xSuppEapolFramesTx=%u\n"
1210 "dot1xSuppEapolStartFramesTx=%u\n"
1211 "dot1xSuppEapolLogoffFramesTx=%u\n"
1212 "dot1xSuppEapolRespFramesTx=%u\n"
1213 "dot1xSuppEapolReqIdFramesRx=%u\n"
1214 "dot1xSuppEapolReqFramesRx=%u\n"
1215 "dot1xSuppInvalidEapolFramesRx=%u\n"
1216 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1217 "dot1xSuppLastEapolFrameVersion=%u\n"
1218 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1219 sm->dot1xSuppEapolFramesRx,
1220 sm->dot1xSuppEapolFramesTx,
1221 sm->dot1xSuppEapolStartFramesTx,
1222 sm->dot1xSuppEapolLogoffFramesTx,
1223 sm->dot1xSuppEapolRespFramesTx,
1224 sm->dot1xSuppEapolReqIdFramesRx,
1225 sm->dot1xSuppEapolReqFramesRx,
1226 sm->dot1xSuppInvalidEapolFramesRx,
1227 sm->dot1xSuppEapLengthErrorFramesRx,
1228 sm->dot1xSuppLastEapolFrameVersion,
1229 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1231 if (os_snprintf_error(buflen - len, ret))
1237 #endif /* CONFIG_CTRL_IFACE */
1241 * eapol_sm_rx_eapol - Process received EAPOL frames
1242 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1243 * @src: Source MAC address of the EAPOL packet
1244 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1245 * @len: Length of the EAPOL frame
1246 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1249 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1252 const struct ieee802_1x_hdr *hdr;
1253 const struct ieee802_1x_eapol_key *key;
1260 sm->dot1xSuppEapolFramesRx++;
1261 if (len < sizeof(*hdr)) {
1262 sm->dot1xSuppInvalidEapolFramesRx++;
1265 hdr = (const struct ieee802_1x_hdr *) buf;
1266 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1267 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1268 if (hdr->version < EAPOL_VERSION) {
1269 /* TODO: backwards compatibility */
1271 plen = be_to_host16(hdr->length);
1272 if (plen > len - sizeof(*hdr)) {
1273 sm->dot1xSuppEapLengthErrorFramesRx++;
1277 if (sm->conf.wps && sm->conf.workaround &&
1278 plen < len - sizeof(*hdr) &&
1279 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1280 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1281 const struct eap_hdr *ehdr =
1282 (const struct eap_hdr *) (hdr + 1);
1285 elen = be_to_host16(ehdr->length);
1286 if (elen > plen && elen <= len - sizeof(*hdr)) {
1288 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1289 * packets with too short EAPOL header length field
1290 * (14 octets). This is fixed in firmware Ver.1.49.
1291 * As a workaround, fix the EAPOL header based on the
1292 * correct length in the EAP packet.
1294 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1295 "payload length based on EAP header: "
1296 "%d -> %d", (int) plen, elen);
1300 #endif /* CONFIG_WPS */
1301 data_len = plen + sizeof(*hdr);
1303 switch (hdr->type) {
1304 case IEEE802_1X_TYPE_EAP_PACKET:
1305 if (sm->conf.workaround) {
1307 * An AP has been reported to send out EAP message with
1308 * undocumented code 10 at some point near the
1309 * completion of EAP authentication. This can result in
1310 * issues with the unexpected EAP message triggering
1311 * restart of EAPOL authentication. Avoid this by
1312 * skipping the message without advancing the state
1315 const struct eap_hdr *ehdr =
1316 (const struct eap_hdr *) (hdr + 1);
1317 if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1318 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1323 if (sm->cached_pmk) {
1324 /* Trying to use PMKSA caching, but Authenticator did
1325 * not seem to have a matching entry. Need to restart
1326 * EAPOL state machines.
1328 eapol_sm_abort_cached(sm);
1330 wpabuf_free(sm->eapReqData);
1331 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1332 if (sm->eapReqData) {
1333 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1335 sm->eapolEap = TRUE;
1336 #ifdef CONFIG_EAP_PROXY
1337 if (sm->use_eap_proxy) {
1338 eap_proxy_packet_update(
1340 wpabuf_mhead_u8(sm->eapReqData),
1341 wpabuf_len(sm->eapReqData));
1342 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1345 #endif /* CONFIG_EAP_PROXY */
1349 case IEEE802_1X_TYPE_EAPOL_KEY:
1350 if (plen < sizeof(*key)) {
1351 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1355 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1356 if (key->type == EAPOL_KEY_TYPE_WPA ||
1357 key->type == EAPOL_KEY_TYPE_RSN) {
1358 /* WPA Supplicant takes care of this frame. */
1359 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1360 "frame in EAPOL state machines");
1364 if (key->type != EAPOL_KEY_TYPE_RC4) {
1365 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1366 "EAPOL-Key type %d", key->type);
1369 os_free(sm->last_rx_key);
1370 sm->last_rx_key = os_malloc(data_len);
1371 if (sm->last_rx_key) {
1372 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1374 os_memcpy(sm->last_rx_key, buf, data_len);
1375 sm->last_rx_key_len = data_len;
1380 #ifdef CONFIG_MACSEC
1381 case IEEE802_1X_TYPE_EAPOL_MKA:
1382 wpa_printf(MSG_EXCESSIVE,
1383 "EAPOL type %d will be handled by MKA",
1386 #endif /* CONFIG_MACSEC */
1388 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1390 sm->dot1xSuppInvalidEapolFramesRx++;
1399 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1400 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1402 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1403 * component, e.g., WPA. This will update the statistics.
1405 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1408 sm->dot1xSuppEapolFramesTx++;
1413 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1414 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1415 * @enabled: New portEnabled value
1417 * Notify EAPOL state machine about new portEnabled value.
1419 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1423 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1424 "portEnabled=%d", enabled);
1425 if (sm->portEnabled != enabled)
1426 sm->force_authorized_update = TRUE;
1427 sm->portEnabled = enabled;
1433 * eapol_sm_notify_portValid - Notification about portValid change
1434 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1435 * @valid: New portValid value
1437 * Notify EAPOL state machine about new portValid value.
1439 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1443 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1444 "portValid=%d", valid);
1445 sm->portValid = valid;
1451 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1452 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1453 * @success: %TRUE = set success, %FALSE = clear success
1455 * Notify the EAPOL state machine that external event has forced EAP state to
1456 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1458 * This function is called to update EAP state when WPA-PSK key handshake has
1459 * been completed successfully since WPA-PSK does not use EAP state machine.
1461 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1465 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1466 "EAP success=%d", success);
1467 sm->eapSuccess = success;
1468 sm->altAccept = success;
1470 eap_notify_success(sm->eap);
1476 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1477 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1478 * @fail: %TRUE = set failure, %FALSE = clear failure
1480 * Notify EAPOL state machine that external event has forced EAP state to
1481 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1483 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1487 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1488 "EAP fail=%d", fail);
1490 sm->altReject = fail;
1496 * eapol_sm_notify_config - Notification of EAPOL configuration change
1497 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1498 * @config: Pointer to current network EAP configuration
1499 * @conf: Pointer to EAPOL configuration data
1501 * Notify EAPOL state machine that configuration has changed. config will be
1502 * stored as a backpointer to network configuration. This can be %NULL to clear
1503 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1504 * data. If conf is %NULL, this part of the configuration change will be
1507 void eapol_sm_notify_config(struct eapol_sm *sm,
1508 struct eap_peer_config *config,
1509 const struct eapol_config *conf)
1514 sm->config = config;
1515 #ifdef CONFIG_EAP_PROXY
1516 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1517 #endif /* CONFIG_EAP_PROXY */
1522 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1523 sm->conf.required_keys = conf->required_keys;
1524 sm->conf.fast_reauth = conf->fast_reauth;
1525 sm->conf.workaround = conf->workaround;
1526 sm->conf.wps = conf->wps;
1527 #ifdef CONFIG_EAP_PROXY
1528 if (sm->use_eap_proxy) {
1529 /* Using EAP Proxy, so skip EAP state machine update */
1532 #endif /* CONFIG_EAP_PROXY */
1534 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1535 eap_set_workaround(sm->eap, conf->workaround);
1536 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1537 eap_set_external_sim(sm->eap, conf->external_sim);
1543 * eapol_sm_get_key - Get master session key (MSK) from EAP
1544 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1545 * @key: Pointer for key buffer
1546 * @len: Number of bytes to copy to key
1547 * Returns: 0 on success (len of key available), maximum available key len
1548 * (>0) if key is available but it is shorter than len, or -1 on failure.
1550 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1551 * is available only after a successful authentication.
1553 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1558 #ifdef CONFIG_EAP_PROXY
1559 if (sm && sm->use_eap_proxy) {
1560 /* Get key from EAP proxy */
1561 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1562 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1565 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1566 if (eap_key == NULL) {
1567 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1573 #endif /* CONFIG_EAP_PROXY */
1574 if (sm == NULL || !eap_key_available(sm->eap)) {
1575 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1578 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1579 if (eap_key == NULL) {
1580 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1583 #ifdef CONFIG_EAP_PROXY
1585 #endif /* CONFIG_EAP_PROXY */
1586 if (len > eap_len) {
1587 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1588 "available (len=%lu)",
1589 (unsigned long) len, (unsigned long) eap_len);
1592 os_memcpy(key, eap_key, len);
1593 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1594 (unsigned long) len);
1600 * eapol_sm_get_session_id - Get EAP Session-Id
1601 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1602 * @len: Pointer to variable that will be set to number of bytes in the session
1603 * Returns: Pointer to the EAP Session-Id or %NULL on failure
1605 * The Session-Id is available only after a successful authentication.
1607 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
1609 if (sm == NULL || !eap_key_available(sm->eap)) {
1610 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
1613 return eap_get_eapSessionId(sm->eap, len);
1618 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1619 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1620 * @logoff: Whether command was logoff
1622 * Notify EAPOL state machines that user requested logon/logoff.
1624 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1627 sm->userLogoff = logoff;
1629 /* If there is a delayed txStart queued, start now. */
1638 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1639 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1641 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1642 * to move EAPOL and EAP state machines into authenticated/successful state.
1644 void eapol_sm_notify_cached(struct eapol_sm *sm)
1648 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1649 sm->eapSuccess = TRUE;
1650 eap_notify_success(sm->eap);
1656 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1657 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1659 * Notify EAPOL state machines if PMKSA caching is used.
1661 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm)
1665 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1666 sm->cached_pmk = TRUE;
1670 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1672 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1673 "doing full EAP authentication");
1676 sm->cached_pmk = FALSE;
1677 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1678 eapol_sm_set_port_unauthorized(sm);
1680 /* Make sure we do not start sending EAPOL-Start frames first, but
1681 * instead move to RESTART state to start EAPOL authentication. */
1683 eapol_enable_timer_tick(sm);
1685 if (sm->ctx->aborted_cached)
1686 sm->ctx->aborted_cached(sm->ctx->ctx);
1691 * eapol_sm_register_scard_ctx - Notification of smart card context
1692 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1693 * @ctx: Context data for smart card operations
1695 * Notify EAPOL state machines of context data for smart card operations. This
1696 * context data will be used as a parameter for scard_*() functions.
1698 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1701 sm->ctx->scard_ctx = ctx;
1702 eap_register_scard_ctx(sm->eap, ctx);
1708 * eapol_sm_notify_portControl - Notification of portControl changes
1709 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1710 * @portControl: New value for portControl variable
1712 * Notify EAPOL state machines that portControl variable has changed.
1714 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1718 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1719 "portControl=%s", eapol_port_control(portControl));
1720 sm->portControl = portControl;
1726 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1727 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1729 * Notify EAPOL state machines that a monitor was attached to the control
1730 * interface to trigger re-sending of pending requests for user input.
1732 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1736 eap_sm_notify_ctrl_attached(sm->eap);
1741 * eapol_sm_notify_ctrl_response - Notification of received user input
1742 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1744 * Notify EAPOL state machines that a control response, i.e., user
1745 * input, was received in order to trigger retrying of a pending EAP request.
1747 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1751 if (sm->eapReqData && !sm->eapReq) {
1752 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1753 "input) notification - retrying pending EAP "
1755 sm->eapolEap = TRUE;
1763 * eapol_sm_request_reauth - Request reauthentication
1764 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1766 * This function can be used to request EAPOL reauthentication, e.g., when the
1767 * current PMKSA entry is nearing expiration.
1769 void eapol_sm_request_reauth(struct eapol_sm *sm)
1771 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1773 eapol_sm_txStart(sm);
1778 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1779 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1780 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1781 * machine loop (eapol_sm_step())
1783 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1784 * successful authentication. This is used to recover from dropped EAP-Success
1787 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1791 eap_notify_lower_layer_success(sm->eap);
1798 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1799 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1801 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1804 eap_invalidate_cached_session(sm->eap);
1808 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1810 struct eapol_sm *sm = ctx;
1811 return sm ? sm->config : NULL;
1815 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1817 struct eapol_sm *sm = ctx;
1818 if (sm == NULL || sm->eapReqData == NULL)
1821 return sm->eapReqData;
1825 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1827 struct eapol_sm *sm = ctx;
1831 case EAPOL_eapSuccess:
1832 return sm->eapSuccess;
1833 case EAPOL_eapRestart:
1834 return sm->eapRestart;
1839 case EAPOL_eapNoResp:
1840 return sm->eapNoResp;
1843 case EAPOL_portEnabled:
1844 return sm->portEnabled;
1845 case EAPOL_altAccept:
1846 return sm->altAccept;
1847 case EAPOL_altReject:
1848 return sm->altReject;
1849 case EAPOL_eapTriggerStart:
1850 return sm->eapTriggerStart;
1856 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1859 struct eapol_sm *sm = ctx;
1863 case EAPOL_eapSuccess:
1864 sm->eapSuccess = value;
1866 case EAPOL_eapRestart:
1867 sm->eapRestart = value;
1870 sm->eapFail = value;
1873 sm->eapResp = value;
1875 case EAPOL_eapNoResp:
1876 sm->eapNoResp = value;
1881 case EAPOL_portEnabled:
1882 sm->portEnabled = value;
1884 case EAPOL_altAccept:
1885 sm->altAccept = value;
1887 case EAPOL_altReject:
1888 sm->altReject = value;
1890 case EAPOL_eapTriggerStart:
1891 sm->eapTriggerStart = value;
1897 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1899 struct eapol_sm *sm = ctx;
1903 case EAPOL_idleWhile:
1904 return sm->idleWhile;
1910 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1913 struct eapol_sm *sm = ctx;
1917 case EAPOL_idleWhile:
1918 sm->idleWhile = value;
1919 if (sm->idleWhile > 0)
1920 eapol_enable_timer_tick(sm);
1926 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1928 #ifndef CONFIG_NO_CONFIG_BLOBS
1929 struct eapol_sm *sm = ctx;
1930 if (sm && sm->ctx && sm->ctx->set_config_blob)
1931 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1932 #endif /* CONFIG_NO_CONFIG_BLOBS */
1936 static const struct wpa_config_blob *
1937 eapol_sm_get_config_blob(void *ctx, const char *name)
1939 #ifndef CONFIG_NO_CONFIG_BLOBS
1940 struct eapol_sm *sm = ctx;
1941 if (sm && sm->ctx && sm->ctx->get_config_blob)
1942 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1945 #else /* CONFIG_NO_CONFIG_BLOBS */
1947 #endif /* CONFIG_NO_CONFIG_BLOBS */
1951 static void eapol_sm_notify_pending(void *ctx)
1953 struct eapol_sm *sm = ctx;
1956 if (sm->eapReqData && !sm->eapReq) {
1957 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1958 "state machine - retrying pending EAP Request");
1959 sm->eapolEap = TRUE;
1966 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1967 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1970 struct eapol_sm *sm = ctx;
1971 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1972 if (sm->ctx->eap_param_needed)
1973 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1975 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1976 #define eapol_sm_eap_param_needed NULL
1977 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1979 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
1980 const char *altsubject[],
1981 int num_altsubject, const char *cert_hash,
1982 const struct wpabuf *cert)
1984 struct eapol_sm *sm = ctx;
1985 if (sm->ctx->cert_cb)
1986 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, altsubject,
1987 num_altsubject, cert_hash, cert);
1991 static void eapol_sm_notify_status(void *ctx, const char *status,
1992 const char *parameter)
1994 struct eapol_sm *sm = ctx;
1996 if (sm->ctx->status_cb)
1997 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
2001 #ifdef CONFIG_EAP_PROXY
2002 static void eapol_sm_eap_proxy_cb(void *ctx)
2004 struct eapol_sm *sm = ctx;
2006 if (sm->ctx->eap_proxy_cb)
2007 sm->ctx->eap_proxy_cb(sm->ctx->ctx);
2009 #endif /* CONFIG_EAP_PROXY */
2012 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
2014 struct eapol_sm *sm = ctx;
2016 if (sm->ctx->set_anon_id)
2017 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
2021 static const struct eapol_callbacks eapol_cb =
2023 eapol_sm_get_config,
2028 eapol_sm_get_eapReqData,
2029 eapol_sm_set_config_blob,
2030 eapol_sm_get_config_blob,
2031 eapol_sm_notify_pending,
2032 eapol_sm_eap_param_needed,
2033 eapol_sm_notify_cert,
2034 eapol_sm_notify_status,
2035 #ifdef CONFIG_EAP_PROXY
2036 eapol_sm_eap_proxy_cb,
2037 #endif /* CONFIG_EAP_PROXY */
2038 eapol_sm_set_anon_id
2043 * eapol_sm_init - Initialize EAPOL state machine
2044 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2045 * and EAPOL state machine will free it in eapol_sm_deinit()
2046 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2048 * Allocate and initialize an EAPOL state machine.
2050 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
2052 struct eapol_sm *sm;
2053 struct eap_config conf;
2054 sm = os_zalloc(sizeof(*sm));
2059 sm->portControl = Auto;
2061 /* Supplicant PAE state machine */
2062 sm->heldPeriod = 60;
2063 sm->startPeriod = 30;
2066 /* Supplicant Backend state machine */
2067 sm->authPeriod = 30;
2069 os_memset(&conf, 0, sizeof(conf));
2070 conf.opensc_engine_path = ctx->opensc_engine_path;
2071 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2072 conf.pkcs11_module_path = ctx->pkcs11_module_path;
2073 conf.openssl_ciphers = ctx->openssl_ciphers;
2074 conf.wps = ctx->wps;
2075 conf.cert_in_cb = ctx->cert_in_cb;
2077 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2078 if (sm->eap == NULL) {
2083 #ifdef CONFIG_EAP_PROXY
2084 sm->use_eap_proxy = FALSE;
2085 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2086 if (sm->eap_proxy == NULL) {
2087 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2089 #endif /* CONFIG_EAP_PROXY */
2091 /* Initialize EAPOL state machines */
2092 sm->force_authorized_update = TRUE;
2093 sm->initialize = TRUE;
2095 sm->initialize = FALSE;
2098 sm->timer_tick_enabled = 1;
2099 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2106 * eapol_sm_deinit - Deinitialize EAPOL state machine
2107 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2109 * Deinitialize and free EAPOL state machine.
2111 void eapol_sm_deinit(struct eapol_sm *sm)
2115 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2116 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2117 eap_peer_sm_deinit(sm->eap);
2118 #ifdef CONFIG_EAP_PROXY
2119 eap_proxy_deinit(sm->eap_proxy);
2120 #endif /* CONFIG_EAP_PROXY */
2121 os_free(sm->last_rx_key);
2122 wpabuf_free(sm->eapReqData);
2128 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2129 struct ext_password_data *ext)
2132 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2136 int eapol_sm_failed(struct eapol_sm *sm)
2140 return !sm->eapSuccess && sm->eapFail;
2144 int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
2146 #ifdef CONFIG_EAP_PROXY
2147 if (sm->eap_proxy == NULL)
2149 return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
2150 #else /* CONFIG_EAP_PROXY */
2152 #endif /* CONFIG_EAP_PROXY */
2156 void eapol_sm_erp_flush(struct eapol_sm *sm)
2159 eap_peer_erp_free_keys(sm->eap);