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.
259 /* Reduce latency on starting WPS negotiation. */
261 #else /* CONFIG_WPS */
263 #endif /* CONFIG_WPS */
265 eapol_enable_timer_tick(sm);
266 sm->eapolEap = FALSE;
268 eapol_sm_txStart(sm);
272 SM_STATE(SUPP_PAE, AUTHENTICATING)
274 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
276 sm->suppSuccess = FALSE;
277 sm->suppFail = FALSE;
278 sm->suppTimeout = FALSE;
281 sm->suppStart = TRUE;
285 SM_STATE(SUPP_PAE, HELD)
287 SM_ENTRY(SUPP_PAE, HELD);
288 sm->heldWhile = sm->heldPeriod;
289 eapol_enable_timer_tick(sm);
290 eapol_sm_set_port_unauthorized(sm);
291 sm->cb_status = EAPOL_CB_FAILURE;
295 SM_STATE(SUPP_PAE, AUTHENTICATED)
297 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
298 eapol_sm_set_port_authorized(sm);
299 sm->cb_status = EAPOL_CB_SUCCESS;
303 SM_STATE(SUPP_PAE, RESTART)
305 SM_ENTRY(SUPP_PAE, RESTART);
306 sm->eapRestart = TRUE;
310 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
312 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
313 eapol_sm_set_port_authorized(sm);
314 sm->sPortMode = ForceAuthorized;
318 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
320 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
321 eapol_sm_set_port_unauthorized(sm);
322 sm->sPortMode = ForceUnauthorized;
323 eapol_sm_txLogoff(sm);
329 if ((sm->userLogoff && !sm->logoffSent) &&
330 !(sm->initialize || !sm->portEnabled))
331 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
332 else if (((sm->portControl == Auto) &&
333 (sm->sPortMode != sm->portControl)) ||
334 sm->initialize || !sm->portEnabled)
335 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
336 else if ((sm->portControl == ForceAuthorized) &&
337 (sm->sPortMode != sm->portControl) &&
338 !(sm->initialize || !sm->portEnabled))
339 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
340 else if ((sm->portControl == ForceUnauthorized) &&
341 (sm->sPortMode != sm->portControl) &&
342 !(sm->initialize || !sm->portEnabled))
343 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
344 else switch (sm->SUPP_PAE_state) {
345 case SUPP_PAE_UNKNOWN:
347 case SUPP_PAE_LOGOFF:
349 SM_ENTER(SUPP_PAE, DISCONNECTED);
351 case SUPP_PAE_DISCONNECTED:
352 SM_ENTER(SUPP_PAE, CONNECTING);
354 case SUPP_PAE_CONNECTING:
355 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
356 SM_ENTER(SUPP_PAE, CONNECTING);
357 else if (sm->startWhen == 0 &&
358 sm->startCount >= sm->maxStart &&
360 SM_ENTER(SUPP_PAE, AUTHENTICATED);
361 else if (sm->eapSuccess || sm->eapFail)
362 SM_ENTER(SUPP_PAE, AUTHENTICATING);
363 else if (sm->eapolEap)
364 SM_ENTER(SUPP_PAE, RESTART);
365 else if (sm->startWhen == 0 &&
366 sm->startCount >= sm->maxStart &&
368 SM_ENTER(SUPP_PAE, HELD);
370 case SUPP_PAE_AUTHENTICATING:
371 if (sm->eapSuccess && !sm->portValid &&
372 sm->conf.accept_802_1x_keys &&
373 sm->conf.required_keys == 0) {
374 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
375 "plaintext connection; no EAPOL-Key frames "
377 sm->portValid = TRUE;
378 if (sm->ctx->eapol_done_cb)
379 sm->ctx->eapol_done_cb(sm->ctx->ctx);
381 if (sm->eapSuccess && sm->portValid)
382 SM_ENTER(SUPP_PAE, AUTHENTICATED);
383 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
384 SM_ENTER(SUPP_PAE, HELD);
385 else if (sm->suppTimeout)
386 SM_ENTER(SUPP_PAE, CONNECTING);
389 if (sm->heldWhile == 0)
390 SM_ENTER(SUPP_PAE, CONNECTING);
391 else if (sm->eapolEap)
392 SM_ENTER(SUPP_PAE, RESTART);
394 case SUPP_PAE_AUTHENTICATED:
395 if (sm->eapolEap && sm->portValid)
396 SM_ENTER(SUPP_PAE, RESTART);
397 else if (!sm->portValid)
398 SM_ENTER(SUPP_PAE, DISCONNECTED);
400 case SUPP_PAE_RESTART:
402 SM_ENTER(SUPP_PAE, AUTHENTICATING);
404 case SUPP_PAE_S_FORCE_AUTH:
406 case SUPP_PAE_S_FORCE_UNAUTH:
412 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
414 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
418 SM_STATE(KEY_RX, KEY_RECEIVE)
420 SM_ENTRY(KEY_RX, KEY_RECEIVE);
421 eapol_sm_processKey(sm);
428 if (sm->initialize || !sm->portEnabled)
429 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
430 switch (sm->KEY_RX_state) {
433 case KEY_RX_NO_KEY_RECEIVE:
435 SM_ENTER(KEY_RX, KEY_RECEIVE);
437 case KEY_RX_KEY_RECEIVE:
439 SM_ENTER(KEY_RX, KEY_RECEIVE);
445 SM_STATE(SUPP_BE, REQUEST)
447 SM_ENTRY(SUPP_BE, REQUEST);
450 eapol_sm_getSuppRsp(sm);
454 SM_STATE(SUPP_BE, RESPONSE)
456 SM_ENTRY(SUPP_BE, RESPONSE);
457 eapol_sm_txSuppRsp(sm);
462 SM_STATE(SUPP_BE, SUCCESS)
464 SM_ENTRY(SUPP_BE, SUCCESS);
466 sm->suppSuccess = TRUE;
468 #ifdef CONFIG_EAP_PROXY
469 if (sm->use_eap_proxy) {
470 if (eap_proxy_key_available(sm->eap_proxy)) {
471 /* New key received - clear IEEE 802.1X EAPOL-Key replay
473 sm->replay_counter_valid = FALSE;
477 #endif /* CONFIG_EAP_PROXY */
479 if (eap_key_available(sm->eap)) {
480 /* New key received - clear IEEE 802.1X EAPOL-Key replay
482 sm->replay_counter_valid = FALSE;
487 SM_STATE(SUPP_BE, FAIL)
489 SM_ENTRY(SUPP_BE, FAIL);
494 SM_STATE(SUPP_BE, TIMEOUT)
496 SM_ENTRY(SUPP_BE, TIMEOUT);
497 sm->suppTimeout = TRUE;
501 SM_STATE(SUPP_BE, IDLE)
503 SM_ENTRY(SUPP_BE, IDLE);
504 sm->suppStart = FALSE;
505 sm->initial_req = TRUE;
509 SM_STATE(SUPP_BE, INITIALIZE)
511 SM_ENTRY(SUPP_BE, INITIALIZE);
512 eapol_sm_abortSupp(sm);
513 sm->suppAbort = FALSE;
516 * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
517 * allows the timer tick to be stopped more quickly when the port is
518 * not enabled. Since this variable is used only within RECEIVE state,
519 * clearing it on initialization does not change actual state machine
526 SM_STATE(SUPP_BE, RECEIVE)
528 SM_ENTRY(SUPP_BE, RECEIVE);
529 sm->authWhile = sm->authPeriod;
530 eapol_enable_timer_tick(sm);
531 sm->eapolEap = FALSE;
532 sm->eapNoResp = FALSE;
533 sm->initial_req = FALSE;
539 if (sm->initialize || sm->suppAbort)
540 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
541 else switch (sm->SUPP_BE_state) {
542 case SUPP_BE_UNKNOWN:
544 case SUPP_BE_REQUEST:
546 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
547 * and SUCCESS based on eapFail and eapSuccess, respectively.
548 * However, IEEE Std 802.1X-2004 is also specifying that
549 * eapNoResp should be set in conjunction with eapSuccess and
550 * eapFail which would mean that more than one of the
551 * transitions here would be activated at the same time.
552 * Skipping RESPONSE and/or RECEIVE states in these cases can
553 * cause problems and the direct transitions to do not seem
554 * correct. Because of this, the conditions for these
555 * transitions are verified only after eapNoResp. They are
556 * unlikely to be used since eapNoResp should always be set if
557 * either of eapSuccess or eapFail is set.
559 if (sm->eapResp && sm->eapNoResp) {
560 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
561 "eapResp and eapNoResp set?!");
564 SM_ENTER(SUPP_BE, RESPONSE);
565 else if (sm->eapNoResp)
566 SM_ENTER(SUPP_BE, RECEIVE);
567 else if (sm->eapFail)
568 SM_ENTER(SUPP_BE, FAIL);
569 else if (sm->eapSuccess)
570 SM_ENTER(SUPP_BE, SUCCESS);
572 case SUPP_BE_RESPONSE:
573 SM_ENTER(SUPP_BE, RECEIVE);
575 case SUPP_BE_SUCCESS:
576 SM_ENTER(SUPP_BE, IDLE);
579 SM_ENTER(SUPP_BE, IDLE);
581 case SUPP_BE_TIMEOUT:
582 SM_ENTER(SUPP_BE, IDLE);
585 if (sm->eapFail && sm->suppStart)
586 SM_ENTER(SUPP_BE, FAIL);
587 else if (sm->eapolEap && sm->suppStart)
588 SM_ENTER(SUPP_BE, REQUEST);
589 else if (sm->eapSuccess && sm->suppStart)
590 SM_ENTER(SUPP_BE, SUCCESS);
592 case SUPP_BE_INITIALIZE:
593 SM_ENTER(SUPP_BE, IDLE);
595 case SUPP_BE_RECEIVE:
597 SM_ENTER(SUPP_BE, REQUEST);
598 else if (sm->eapFail)
599 SM_ENTER(SUPP_BE, FAIL);
600 else if (sm->authWhile == 0)
601 SM_ENTER(SUPP_BE, TIMEOUT);
602 else if (sm->eapSuccess)
603 SM_ENTER(SUPP_BE, SUCCESS);
609 static void eapol_sm_txLogoff(struct eapol_sm *sm)
611 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
612 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
613 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
614 sm->dot1xSuppEapolLogoffFramesTx++;
615 sm->dot1xSuppEapolFramesTx++;
619 static void eapol_sm_txStart(struct eapol_sm *sm)
621 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
622 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
623 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
624 sm->dot1xSuppEapolStartFramesTx++;
625 sm->dot1xSuppEapolFramesTx++;
629 #define IEEE8021X_ENCR_KEY_LEN 32
630 #define IEEE8021X_SIGN_KEY_LEN 32
632 struct eap_key_data {
633 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
634 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
638 static void eapol_sm_processKey(struct eapol_sm *sm)
641 struct ieee802_1x_hdr *hdr;
642 struct ieee802_1x_eapol_key *key;
643 struct eap_key_data keydata;
644 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
645 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
646 int key_len, res, sign_key_len, encr_key_len;
650 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
651 if (sm->last_rx_key == NULL)
654 if (!sm->conf.accept_802_1x_keys) {
655 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
656 " even though this was not accepted - "
657 "ignoring this packet");
661 if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
663 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
664 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
665 plen = be_to_host16(hdr->length);
666 if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
667 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
670 rx_key_length = WPA_GET_BE16(key->key_length);
671 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
672 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
673 hdr->version, hdr->type, be_to_host16(hdr->length),
674 key->type, rx_key_length, key->key_index);
676 eapol_sm_notify_lower_layer_success(sm, 1);
677 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
678 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
679 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
681 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
682 "decrypting EAPOL-Key keys");
686 /* LEAP derives only 16 bytes of keying material. */
687 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
689 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
690 "master key for decrypting EAPOL-Key keys");
695 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
697 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
698 "data for decrypting EAPOL-Key keys (res=%d)", res);
702 /* The key replay_counter must increase when same master key */
703 if (sm->replay_counter_valid &&
704 os_memcmp(sm->last_replay_counter, key->replay_counter,
705 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
706 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
707 "not increase - ignoring key");
708 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
709 sm->last_replay_counter,
710 IEEE8021X_REPLAY_COUNTER_LEN);
711 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
712 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
716 /* Verify key signature (HMAC-MD5) */
717 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
718 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
719 hmac_md5(keydata.sign_key, sign_key_len,
720 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
722 if (os_memcmp(orig_key_sign, key->key_signature,
723 IEEE8021X_KEY_SIGN_LEN) != 0) {
724 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
726 os_memcpy(key->key_signature, orig_key_sign,
727 IEEE8021X_KEY_SIGN_LEN);
730 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
732 key_len = plen - sizeof(*key);
733 if (key_len > 32 || rx_key_length > 32) {
734 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
735 key_len ? key_len : rx_key_length);
738 if (key_len == rx_key_length) {
739 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
740 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
742 os_memcpy(datakey, key + 1, key_len);
743 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
745 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
747 } else if (key_len == 0) {
749 * IEEE 802.1X-2004 specifies that least significant Key Length
750 * octets from MS-MPPE-Send-Key are used as the key if the key
751 * data is not present. This seems to be meaning the beginning
752 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
753 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
754 * Anyway, taking the beginning of the keying material from EAP
755 * seems to interoperate with Authenticators.
757 key_len = rx_key_length;
758 os_memcpy(datakey, keydata.encr_key, key_len);
759 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
760 "material data encryption key",
763 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
764 "(key_length=%d)", key_len, rx_key_length);
768 sm->replay_counter_valid = TRUE;
769 os_memcpy(sm->last_replay_counter, key->replay_counter,
770 IEEE8021X_REPLAY_COUNTER_LEN);
772 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
774 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
775 "unicast" : "broadcast",
776 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
778 if (sm->ctx->set_wep_key &&
779 sm->ctx->set_wep_key(sm->ctx->ctx,
780 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
781 key->key_index & IEEE8021X_KEY_INDEX_MASK,
782 datakey, key_len) < 0) {
783 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
786 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
787 sm->unicast_key_received = TRUE;
789 sm->broadcast_key_received = TRUE;
791 if ((sm->unicast_key_received ||
792 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
793 (sm->broadcast_key_received ||
794 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
796 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
798 sm->portValid = TRUE;
799 if (sm->ctx->eapol_done_cb)
800 sm->ctx->eapol_done_cb(sm->ctx->ctx);
803 #endif /* CONFIG_FIPS */
807 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
809 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
810 /* EAP layer processing; no special code is needed, since Supplicant
811 * Backend state machine is waiting for eapNoResp or eapResp to be set
812 * and these are only set in the EAP state machine when the processing
817 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
821 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
823 #ifdef CONFIG_EAP_PROXY
824 if (sm->use_eap_proxy) {
825 /* Get EAP Response from EAP Proxy */
826 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
828 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
829 "response data not available");
833 #endif /* CONFIG_EAP_PROXY */
835 resp = eap_get_eapRespData(sm->eap);
837 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
842 /* Send EAP-Packet from the EAP layer to the Authenticator */
843 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
844 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
847 /* eapRespData is not used anymore, so free it here */
851 sm->dot1xSuppEapolReqIdFramesRx++;
853 sm->dot1xSuppEapolReqFramesRx++;
854 sm->dot1xSuppEapolRespFramesTx++;
855 sm->dot1xSuppEapolFramesTx++;
859 static void eapol_sm_abortSupp(struct eapol_sm *sm)
861 /* release system resources that may have been allocated for the
862 * authentication session */
863 os_free(sm->last_rx_key);
864 sm->last_rx_key = NULL;
865 wpabuf_free(sm->eapReqData);
866 sm->eapReqData = NULL;
867 eap_sm_abort(sm->eap);
871 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
873 eapol_sm_step(timeout_ctx);
877 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
881 cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
882 sm->force_authorized_update = FALSE;
883 sm->suppPortStatus = Authorized;
884 if (cb && sm->ctx->port_cb)
885 sm->ctx->port_cb(sm->ctx->ctx, 1);
889 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
893 cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
894 sm->force_authorized_update = FALSE;
895 sm->suppPortStatus = Unauthorized;
896 if (cb && sm->ctx->port_cb)
897 sm->ctx->port_cb(sm->ctx->ctx, 0);
902 * eapol_sm_step - EAPOL state machine step function
903 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
905 * This function is called to notify the state machine about changed external
906 * variables. It will step through the EAPOL state machines in loop to process
907 * all triggered state changes.
909 void eapol_sm_step(struct eapol_sm *sm)
913 /* In theory, it should be ok to run this in loop until !changed.
914 * However, it is better to use a limit on number of iterations to
915 * allow events (e.g., SIGTERM) to stop the program cleanly if the
916 * state machine were to generate a busy loop. */
917 for (i = 0; i < 100; i++) {
919 SM_STEP_RUN(SUPP_PAE);
921 SM_STEP_RUN(SUPP_BE);
922 #ifdef CONFIG_EAP_PROXY
923 if (sm->use_eap_proxy) {
924 /* Drive the EAP proxy state machine */
925 if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
928 #endif /* CONFIG_EAP_PROXY */
929 if (eap_peer_sm_step(sm->eap))
936 /* restart EAPOL state machine step from timeout call in order
937 * to allow other events to be processed. */
938 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
939 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
942 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
943 enum eapol_supp_result result;
944 if (sm->cb_status == EAPOL_CB_SUCCESS)
945 result = EAPOL_SUPP_RESULT_SUCCESS;
946 else if (eap_peer_was_failure_expected(sm->eap))
947 result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
949 result = EAPOL_SUPP_RESULT_FAILURE;
950 sm->cb_status = EAPOL_CB_IN_PROGRESS;
951 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
956 #ifdef CONFIG_CTRL_IFACE
957 static const char *eapol_supp_pae_state(int state)
960 case SUPP_PAE_LOGOFF:
962 case SUPP_PAE_DISCONNECTED:
963 return "DISCONNECTED";
964 case SUPP_PAE_CONNECTING:
966 case SUPP_PAE_AUTHENTICATING:
967 return "AUTHENTICATING";
970 case SUPP_PAE_AUTHENTICATED:
971 return "AUTHENTICATED";
972 case SUPP_PAE_RESTART:
980 static const char *eapol_supp_be_state(int state)
983 case SUPP_BE_REQUEST:
985 case SUPP_BE_RESPONSE:
987 case SUPP_BE_SUCCESS:
991 case SUPP_BE_TIMEOUT:
995 case SUPP_BE_INITIALIZE:
997 case SUPP_BE_RECEIVE:
1005 static const char * eapol_port_status(PortStatus status)
1007 if (status == Authorized)
1008 return "Authorized";
1010 return "Unauthorized";
1012 #endif /* CONFIG_CTRL_IFACE */
1015 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1016 static const char * eapol_port_control(PortControl ctrl)
1021 case ForceUnauthorized:
1022 return "ForceUnauthorized";
1023 case ForceAuthorized:
1024 return "ForceAuthorized";
1029 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1033 * eapol_sm_configure - Set EAPOL variables
1034 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1035 * @heldPeriod: dot1xSuppHeldPeriod
1036 * @authPeriod: dot1xSuppAuthPeriod
1037 * @startPeriod: dot1xSuppStartPeriod
1038 * @maxStart: dot1xSuppMaxStart
1040 * Set configurable EAPOL state machine variables. Each variable can be set to
1041 * the given value or ignored if set to -1 (to set only some of the variables).
1043 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1044 int startPeriod, int maxStart)
1048 if (heldPeriod >= 0)
1049 sm->heldPeriod = heldPeriod;
1050 if (authPeriod >= 0)
1051 sm->authPeriod = authPeriod;
1052 if (startPeriod >= 0)
1053 sm->startPeriod = startPeriod;
1055 sm->maxStart = maxStart;
1060 * eapol_sm_get_method_name - Get EAPOL method name
1061 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1062 * Returns: Static string containing name of current eap method or NULL
1064 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1066 if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1067 sm->suppPortStatus != Authorized)
1070 return eap_sm_get_method_name(sm->eap);
1074 #ifdef CONFIG_CTRL_IFACE
1076 * eapol_sm_get_status - Get EAPOL state machine status
1077 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1078 * @buf: Buffer for status information
1079 * @buflen: Maximum buffer length
1080 * @verbose: Whether to include verbose status information
1081 * Returns: Number of bytes written to buf.
1083 * Query EAPOL state machine for status information. This function fills in a
1084 * text area with current status information from the EAPOL state machine. If
1085 * the buffer (buf) is not large enough, status information will be truncated
1086 * to fit the buffer.
1088 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1095 len = os_snprintf(buf, buflen,
1096 "Supplicant PAE state=%s\n"
1097 "suppPortStatus=%s\n",
1098 eapol_supp_pae_state(sm->SUPP_PAE_state),
1099 eapol_port_status(sm->suppPortStatus));
1100 if (len < 0 || (size_t) len >= buflen)
1104 ret = os_snprintf(buf + len, buflen - len,
1110 "Supplicant Backend state=%s\n",
1115 eapol_port_control(sm->portControl),
1116 eapol_supp_be_state(sm->SUPP_BE_state));
1117 if (ret < 0 || (size_t) ret >= buflen - len)
1122 #ifdef CONFIG_EAP_PROXY
1123 if (sm->use_eap_proxy)
1124 len += eap_proxy_sm_get_status(sm->eap_proxy,
1125 buf + len, buflen - len,
1128 #endif /* CONFIG_EAP_PROXY */
1129 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1136 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1137 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1138 * @buf: Buffer for MIB information
1139 * @buflen: Maximum buffer length
1140 * Returns: Number of bytes written to buf.
1142 * Query EAPOL state machine for MIB information. This function fills in a
1143 * text area with current MIB information from the EAPOL state machine. If
1144 * the buffer (buf) is not large enough, MIB information will be truncated to
1147 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1154 ret = os_snprintf(buf, buflen,
1155 "dot1xSuppPaeState=%d\n"
1156 "dot1xSuppHeldPeriod=%u\n"
1157 "dot1xSuppAuthPeriod=%u\n"
1158 "dot1xSuppStartPeriod=%u\n"
1159 "dot1xSuppMaxStart=%u\n"
1160 "dot1xSuppSuppControlledPortStatus=%s\n"
1161 "dot1xSuppBackendPaeState=%d\n",
1167 sm->suppPortStatus == Authorized ?
1168 "Authorized" : "Unauthorized",
1171 if (ret < 0 || (size_t) ret >= buflen)
1175 ret = os_snprintf(buf + len, buflen - len,
1176 "dot1xSuppEapolFramesRx=%u\n"
1177 "dot1xSuppEapolFramesTx=%u\n"
1178 "dot1xSuppEapolStartFramesTx=%u\n"
1179 "dot1xSuppEapolLogoffFramesTx=%u\n"
1180 "dot1xSuppEapolRespFramesTx=%u\n"
1181 "dot1xSuppEapolReqIdFramesRx=%u\n"
1182 "dot1xSuppEapolReqFramesRx=%u\n"
1183 "dot1xSuppInvalidEapolFramesRx=%u\n"
1184 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1185 "dot1xSuppLastEapolFrameVersion=%u\n"
1186 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1187 sm->dot1xSuppEapolFramesRx,
1188 sm->dot1xSuppEapolFramesTx,
1189 sm->dot1xSuppEapolStartFramesTx,
1190 sm->dot1xSuppEapolLogoffFramesTx,
1191 sm->dot1xSuppEapolRespFramesTx,
1192 sm->dot1xSuppEapolReqIdFramesRx,
1193 sm->dot1xSuppEapolReqFramesRx,
1194 sm->dot1xSuppInvalidEapolFramesRx,
1195 sm->dot1xSuppEapLengthErrorFramesRx,
1196 sm->dot1xSuppLastEapolFrameVersion,
1197 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1199 if (ret < 0 || (size_t) ret >= buflen - len)
1205 #endif /* CONFIG_CTRL_IFACE */
1209 * eapol_sm_rx_eapol - Process received EAPOL frames
1210 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1211 * @src: Source MAC address of the EAPOL packet
1212 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1213 * @len: Length of the EAPOL frame
1214 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1217 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1220 const struct ieee802_1x_hdr *hdr;
1221 const struct ieee802_1x_eapol_key *key;
1228 sm->dot1xSuppEapolFramesRx++;
1229 if (len < sizeof(*hdr)) {
1230 sm->dot1xSuppInvalidEapolFramesRx++;
1233 hdr = (const struct ieee802_1x_hdr *) buf;
1234 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1235 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1236 if (hdr->version < EAPOL_VERSION) {
1237 /* TODO: backwards compatibility */
1239 plen = be_to_host16(hdr->length);
1240 if (plen > len - sizeof(*hdr)) {
1241 sm->dot1xSuppEapLengthErrorFramesRx++;
1245 if (sm->conf.workaround &&
1246 plen < len - sizeof(*hdr) &&
1247 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1248 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1249 const struct eap_hdr *ehdr =
1250 (const struct eap_hdr *) (hdr + 1);
1253 elen = be_to_host16(ehdr->length);
1254 if (elen > plen && elen <= len - sizeof(*hdr)) {
1256 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1257 * packets with too short EAPOL header length field
1258 * (14 octets). This is fixed in firmware Ver.1.49.
1259 * As a workaround, fix the EAPOL header based on the
1260 * correct length in the EAP packet.
1262 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1263 "payload length based on EAP header: "
1264 "%d -> %d", (int) plen, elen);
1268 #endif /* CONFIG_WPS */
1269 data_len = plen + sizeof(*hdr);
1271 switch (hdr->type) {
1272 case IEEE802_1X_TYPE_EAP_PACKET:
1273 if (sm->conf.workaround) {
1275 * An AP has been reported to send out EAP message with
1276 * undocumented code 10 at some point near the
1277 * completion of EAP authentication. This can result in
1278 * issues with the unexpected EAP message triggering
1279 * restart of EAPOL authentication. Avoid this by
1280 * skipping the message without advancing the state
1283 const struct eap_hdr *ehdr =
1284 (const struct eap_hdr *) (hdr + 1);
1285 if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1286 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1291 if (sm->cached_pmk) {
1292 /* Trying to use PMKSA caching, but Authenticator did
1293 * not seem to have a matching entry. Need to restart
1294 * EAPOL state machines.
1296 eapol_sm_abort_cached(sm);
1298 wpabuf_free(sm->eapReqData);
1299 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1300 if (sm->eapReqData) {
1301 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1303 sm->eapolEap = TRUE;
1304 #ifdef CONFIG_EAP_PROXY
1305 if (sm->use_eap_proxy) {
1306 eap_proxy_packet_update(
1308 wpabuf_mhead_u8(sm->eapReqData),
1309 wpabuf_len(sm->eapReqData));
1310 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1313 #endif /* CONFIG_EAP_PROXY */
1317 case IEEE802_1X_TYPE_EAPOL_KEY:
1318 if (plen < sizeof(*key)) {
1319 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1323 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1324 if (key->type == EAPOL_KEY_TYPE_WPA ||
1325 key->type == EAPOL_KEY_TYPE_RSN) {
1326 /* WPA Supplicant takes care of this frame. */
1327 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1328 "frame in EAPOL state machines");
1332 if (key->type != EAPOL_KEY_TYPE_RC4) {
1333 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1334 "EAPOL-Key type %d", key->type);
1337 os_free(sm->last_rx_key);
1338 sm->last_rx_key = os_malloc(data_len);
1339 if (sm->last_rx_key) {
1340 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1342 os_memcpy(sm->last_rx_key, buf, data_len);
1343 sm->last_rx_key_len = data_len;
1349 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1351 sm->dot1xSuppInvalidEapolFramesRx++;
1360 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1361 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1363 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1364 * component, e.g., WPA. This will update the statistics.
1366 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1369 sm->dot1xSuppEapolFramesTx++;
1374 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1375 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1376 * @enabled: New portEnabled value
1378 * Notify EAPOL state machine about new portEnabled value.
1380 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1384 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1385 "portEnabled=%d", enabled);
1386 if (sm->portEnabled != enabled)
1387 sm->force_authorized_update = TRUE;
1388 sm->portEnabled = enabled;
1394 * eapol_sm_notify_portValid - Notification about portValid change
1395 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1396 * @valid: New portValid value
1398 * Notify EAPOL state machine about new portValid value.
1400 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1404 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1405 "portValid=%d", valid);
1406 sm->portValid = valid;
1412 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1413 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1414 * @success: %TRUE = set success, %FALSE = clear success
1416 * Notify the EAPOL state machine that external event has forced EAP state to
1417 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1419 * This function is called to update EAP state when WPA-PSK key handshake has
1420 * been completed successfully since WPA-PSK does not use EAP state machine.
1422 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1426 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1427 "EAP success=%d", success);
1428 sm->eapSuccess = success;
1429 sm->altAccept = success;
1431 eap_notify_success(sm->eap);
1437 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1438 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1439 * @fail: %TRUE = set failure, %FALSE = clear failure
1441 * Notify EAPOL state machine that external event has forced EAP state to
1442 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1444 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1448 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1449 "EAP fail=%d", fail);
1451 sm->altReject = fail;
1457 * eapol_sm_notify_config - Notification of EAPOL configuration change
1458 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1459 * @config: Pointer to current network EAP configuration
1460 * @conf: Pointer to EAPOL configuration data
1462 * Notify EAPOL state machine that configuration has changed. config will be
1463 * stored as a backpointer to network configuration. This can be %NULL to clear
1464 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1465 * data. If conf is %NULL, this part of the configuration change will be
1468 void eapol_sm_notify_config(struct eapol_sm *sm,
1469 struct eap_peer_config *config,
1470 const struct eapol_config *conf)
1475 sm->config = config;
1476 #ifdef CONFIG_EAP_PROXY
1477 sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1478 #endif /* CONFIG_EAP_PROXY */
1483 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1484 sm->conf.required_keys = conf->required_keys;
1485 sm->conf.fast_reauth = conf->fast_reauth;
1486 sm->conf.workaround = conf->workaround;
1487 #ifdef CONFIG_EAP_PROXY
1488 if (sm->use_eap_proxy) {
1489 /* Using EAP Proxy, so skip EAP state machine update */
1492 #endif /* CONFIG_EAP_PROXY */
1494 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1495 eap_set_workaround(sm->eap, conf->workaround);
1496 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1497 eap_set_external_sim(sm->eap, conf->external_sim);
1503 * eapol_sm_get_key - Get master session key (MSK) from EAP
1504 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1505 * @key: Pointer for key buffer
1506 * @len: Number of bytes to copy to key
1507 * Returns: 0 on success (len of key available), maximum available key len
1508 * (>0) if key is available but it is shorter than len, or -1 on failure.
1510 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1511 * is available only after a successful authentication.
1513 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1518 #ifdef CONFIG_EAP_PROXY
1519 if (sm->use_eap_proxy) {
1520 /* Get key from EAP proxy */
1521 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1522 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1525 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1526 if (eap_key == NULL) {
1527 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1533 #endif /* CONFIG_EAP_PROXY */
1534 if (sm == NULL || !eap_key_available(sm->eap)) {
1535 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1538 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1539 if (eap_key == NULL) {
1540 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1543 #ifdef CONFIG_EAP_PROXY
1545 #endif /* CONFIG_EAP_PROXY */
1546 if (len > eap_len) {
1547 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1548 "available (len=%lu)",
1549 (unsigned long) len, (unsigned long) eap_len);
1552 os_memcpy(key, eap_key, len);
1553 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1554 (unsigned long) len);
1560 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1561 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1562 * @logoff: Whether command was logoff
1564 * Notify EAPOL state machines that user requested logon/logoff.
1566 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1569 sm->userLogoff = logoff;
1571 /* If there is a delayed txStart queued, start now. */
1580 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1581 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1583 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1584 * to move EAPOL and EAP state machines into authenticated/successful state.
1586 void eapol_sm_notify_cached(struct eapol_sm *sm)
1590 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1591 sm->eapSuccess = TRUE;
1592 eap_notify_success(sm->eap);
1598 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1599 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1600 * @attempt: Whether PMKSA caching is tried
1602 * Notify EAPOL state machines whether PMKSA caching is used.
1604 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
1609 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1610 sm->cached_pmk = TRUE;
1612 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
1613 sm->cached_pmk = FALSE;
1618 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1620 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1621 "doing full EAP authentication");
1624 sm->cached_pmk = FALSE;
1625 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1626 eapol_sm_set_port_unauthorized(sm);
1628 /* Make sure we do not start sending EAPOL-Start frames first, but
1629 * instead move to RESTART state to start EAPOL authentication. */
1631 eapol_enable_timer_tick(sm);
1633 if (sm->ctx->aborted_cached)
1634 sm->ctx->aborted_cached(sm->ctx->ctx);
1639 * eapol_sm_register_scard_ctx - Notification of smart card context
1640 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1641 * @ctx: Context data for smart card operations
1643 * Notify EAPOL state machines of context data for smart card operations. This
1644 * context data will be used as a parameter for scard_*() functions.
1646 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1649 sm->ctx->scard_ctx = ctx;
1650 eap_register_scard_ctx(sm->eap, ctx);
1656 * eapol_sm_notify_portControl - Notification of portControl changes
1657 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1658 * @portControl: New value for portControl variable
1660 * Notify EAPOL state machines that portControl variable has changed.
1662 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1666 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1667 "portControl=%s", eapol_port_control(portControl));
1668 sm->portControl = portControl;
1674 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1675 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1677 * Notify EAPOL state machines that a monitor was attached to the control
1678 * interface to trigger re-sending of pending requests for user input.
1680 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1684 eap_sm_notify_ctrl_attached(sm->eap);
1689 * eapol_sm_notify_ctrl_response - Notification of received user input
1690 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1692 * Notify EAPOL state machines that a control response, i.e., user
1693 * input, was received in order to trigger retrying of a pending EAP request.
1695 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1699 if (sm->eapReqData && !sm->eapReq) {
1700 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1701 "input) notification - retrying pending EAP "
1703 sm->eapolEap = TRUE;
1711 * eapol_sm_request_reauth - Request reauthentication
1712 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1714 * This function can be used to request EAPOL reauthentication, e.g., when the
1715 * current PMKSA entry is nearing expiration.
1717 void eapol_sm_request_reauth(struct eapol_sm *sm)
1719 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1721 eapol_sm_txStart(sm);
1726 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1727 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1728 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1729 * machine loop (eapol_sm_step())
1731 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1732 * successful authentication. This is used to recover from dropped EAP-Success
1735 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1739 eap_notify_lower_layer_success(sm->eap);
1746 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1747 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1749 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1752 eap_invalidate_cached_session(sm->eap);
1756 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1758 struct eapol_sm *sm = ctx;
1759 return sm ? sm->config : NULL;
1763 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1765 struct eapol_sm *sm = ctx;
1766 if (sm == NULL || sm->eapReqData == NULL)
1769 return sm->eapReqData;
1773 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1775 struct eapol_sm *sm = ctx;
1779 case EAPOL_eapSuccess:
1780 return sm->eapSuccess;
1781 case EAPOL_eapRestart:
1782 return sm->eapRestart;
1787 case EAPOL_eapNoResp:
1788 return sm->eapNoResp;
1791 case EAPOL_portEnabled:
1792 return sm->portEnabled;
1793 case EAPOL_altAccept:
1794 return sm->altAccept;
1795 case EAPOL_altReject:
1796 return sm->altReject;
1802 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1805 struct eapol_sm *sm = ctx;
1809 case EAPOL_eapSuccess:
1810 sm->eapSuccess = value;
1812 case EAPOL_eapRestart:
1813 sm->eapRestart = value;
1816 sm->eapFail = value;
1819 sm->eapResp = value;
1821 case EAPOL_eapNoResp:
1822 sm->eapNoResp = value;
1827 case EAPOL_portEnabled:
1828 sm->portEnabled = value;
1830 case EAPOL_altAccept:
1831 sm->altAccept = value;
1833 case EAPOL_altReject:
1834 sm->altReject = value;
1840 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1842 struct eapol_sm *sm = ctx;
1846 case EAPOL_idleWhile:
1847 return sm->idleWhile;
1853 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1856 struct eapol_sm *sm = ctx;
1860 case EAPOL_idleWhile:
1861 sm->idleWhile = value;
1862 if (sm->idleWhile > 0)
1863 eapol_enable_timer_tick(sm);
1869 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1871 #ifndef CONFIG_NO_CONFIG_BLOBS
1872 struct eapol_sm *sm = ctx;
1873 if (sm && sm->ctx && sm->ctx->set_config_blob)
1874 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1875 #endif /* CONFIG_NO_CONFIG_BLOBS */
1879 static const struct wpa_config_blob *
1880 eapol_sm_get_config_blob(void *ctx, const char *name)
1882 #ifndef CONFIG_NO_CONFIG_BLOBS
1883 struct eapol_sm *sm = ctx;
1884 if (sm && sm->ctx && sm->ctx->get_config_blob)
1885 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1888 #else /* CONFIG_NO_CONFIG_BLOBS */
1890 #endif /* CONFIG_NO_CONFIG_BLOBS */
1894 static void eapol_sm_notify_pending(void *ctx)
1896 struct eapol_sm *sm = ctx;
1899 if (sm->eapReqData && !sm->eapReq) {
1900 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1901 "state machine - retrying pending EAP Request");
1902 sm->eapolEap = TRUE;
1909 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1910 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1913 struct eapol_sm *sm = ctx;
1914 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1915 if (sm->ctx->eap_param_needed)
1916 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1918 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1919 #define eapol_sm_eap_param_needed NULL
1920 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1922 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
1923 const char *cert_hash,
1924 const struct wpabuf *cert)
1926 struct eapol_sm *sm = ctx;
1927 if (sm->ctx->cert_cb)
1928 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
1933 static void eapol_sm_notify_status(void *ctx, const char *status,
1934 const char *parameter)
1936 struct eapol_sm *sm = ctx;
1938 if (sm->ctx->status_cb)
1939 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
1943 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
1945 struct eapol_sm *sm = ctx;
1947 if (sm->ctx->set_anon_id)
1948 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
1952 static struct eapol_callbacks eapol_cb =
1954 eapol_sm_get_config,
1959 eapol_sm_get_eapReqData,
1960 eapol_sm_set_config_blob,
1961 eapol_sm_get_config_blob,
1962 eapol_sm_notify_pending,
1963 eapol_sm_eap_param_needed,
1964 eapol_sm_notify_cert,
1965 eapol_sm_notify_status,
1966 eapol_sm_set_anon_id
1971 * eapol_sm_init - Initialize EAPOL state machine
1972 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
1973 * and EAPOL state machine will free it in eapol_sm_deinit()
1974 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
1976 * Allocate and initialize an EAPOL state machine.
1978 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
1980 struct eapol_sm *sm;
1981 struct eap_config conf;
1982 sm = os_zalloc(sizeof(*sm));
1987 sm->portControl = Auto;
1989 /* Supplicant PAE state machine */
1990 sm->heldPeriod = 60;
1991 sm->startPeriod = 30;
1994 /* Supplicant Backend state machine */
1995 sm->authPeriod = 30;
1997 os_memset(&conf, 0, sizeof(conf));
1998 conf.opensc_engine_path = ctx->opensc_engine_path;
1999 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2000 conf.pkcs11_module_path = ctx->pkcs11_module_path;
2001 conf.wps = ctx->wps;
2002 conf.cert_in_cb = ctx->cert_in_cb;
2004 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2005 if (sm->eap == NULL) {
2010 #ifdef CONFIG_EAP_PROXY
2011 sm->use_eap_proxy = FALSE;
2012 sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2013 if (sm->eap_proxy == NULL) {
2014 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2016 #endif /* CONFIG_EAP_PROXY */
2018 /* Initialize EAPOL state machines */
2019 sm->force_authorized_update = TRUE;
2020 sm->initialize = TRUE;
2022 sm->initialize = FALSE;
2025 sm->timer_tick_enabled = 1;
2026 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2033 * eapol_sm_deinit - Deinitialize EAPOL state machine
2034 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2036 * Deinitialize and free EAPOL state machine.
2038 void eapol_sm_deinit(struct eapol_sm *sm)
2042 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2043 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2044 eap_peer_sm_deinit(sm->eap);
2045 #ifdef CONFIG_EAP_PROXY
2046 eap_proxy_deinit(sm->eap_proxy);
2047 #endif /* CONFIG_EAP_PROXY */
2048 os_free(sm->last_rx_key);
2049 wpabuf_free(sm->eapReqData);
2055 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2056 struct ext_password_data *ext)
2059 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2063 int eapol_sm_failed(struct eapol_sm *sm)
2067 return !sm->eapSuccess && sm->eapFail;
2071 int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len)
2073 #ifdef CONFIG_EAP_PROXY
2074 if (sm->eap_proxy == NULL)
2076 return eap_proxy_get_imsi(sm->eap_proxy, imsi, len);
2077 #else /* CONFIG_EAP_PROXY */
2079 #endif /* CONFIG_EAP_PROXY */