2 * EAPOL supplicant state machines
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "eapol_supp_sm.h"
19 #include "eap_peer/eap.h"
21 #include "eapol_common.h"
24 #include "state_machine.h"
27 #define STATE_MACHINE_DATA struct eapol_sm
28 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
31 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
34 * struct eapol_sm - Internal data for EAPOL state machines
38 unsigned int authWhile;
39 unsigned int heldWhile;
40 unsigned int startWhen;
41 unsigned int idleWhile; /* for EAP state machine */
42 int timer_tick_enabled;
44 /* Global variables */
51 PortControl portControl;
53 PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
61 /* Supplicant PAE state machine */
64 SUPP_PAE_DISCONNECTED = 1,
66 SUPP_PAE_CONNECTING = 3,
67 SUPP_PAE_AUTHENTICATING = 4,
68 SUPP_PAE_AUTHENTICATED = 5,
72 SUPP_PAE_S_FORCE_AUTH = 9,
73 SUPP_PAE_S_FORCE_UNAUTH = 10
74 } SUPP_PAE_state; /* dot1xSuppPaeState */
78 unsigned int startCount;
80 PortControl sPortMode;
82 unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
83 unsigned int startPeriod; /* dot1xSuppStartPeriod */
84 unsigned int maxStart; /* dot1xSuppMaxStart */
86 /* Key Receive state machine */
89 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
94 /* Supplicant Backend state machine */
97 SUPP_BE_INITIALIZE = 1,
101 SUPP_BE_RESPONSE = 5,
105 } SUPP_BE_state; /* dot1xSuppBackendPaeState */
111 unsigned int authPeriod; /* dot1xSuppAuthPeriod */
114 unsigned int dot1xSuppEapolFramesRx;
115 unsigned int dot1xSuppEapolFramesTx;
116 unsigned int dot1xSuppEapolStartFramesTx;
117 unsigned int dot1xSuppEapolLogoffFramesTx;
118 unsigned int dot1xSuppEapolRespFramesTx;
119 unsigned int dot1xSuppEapolReqIdFramesRx;
120 unsigned int dot1xSuppEapolReqFramesRx;
121 unsigned int dot1xSuppInvalidEapolFramesRx;
122 unsigned int dot1xSuppEapLengthErrorFramesRx;
123 unsigned int dot1xSuppLastEapolFrameVersion;
124 unsigned char dot1xSuppLastEapolFrameSource[6];
126 /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
129 struct eap_peer_config *config;
132 size_t last_rx_key_len;
133 struct wpabuf *eapReqData; /* for EAP */
134 Boolean altAccept; /* for EAP */
135 Boolean altReject; /* for EAP */
136 Boolean replay_counter_valid;
137 u8 last_replay_counter[16];
138 struct eapol_config conf;
139 struct eapol_ctx *ctx;
140 enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
144 Boolean unicast_key_received, broadcast_key_received;
148 #define IEEE8021X_REPLAY_COUNTER_LEN 8
149 #define IEEE8021X_KEY_SIGN_LEN 16
150 #define IEEE8021X_KEY_IV_LEN 16
152 #define IEEE8021X_KEY_INDEX_FLAG 0x80
153 #define IEEE8021X_KEY_INDEX_MASK 0x03
156 #pragma pack(push, 1)
157 #endif /* _MSC_VER */
159 struct ieee802_1x_eapol_key {
161 /* Note: key_length is unaligned */
163 /* does not repeat within the life of the keying material used to
164 * encrypt the Key field; 64-bit NTP timestamp MAY be used here */
165 u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
166 u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
167 u8 key_index; /* key flag in the most significant bit:
168 * 0 = broadcast (default key),
169 * 1 = unicast (key mapping key); key index is in the
170 * 7 least significant bits */
171 /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
173 u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
175 /* followed by key: if packet body length = 44 + key length, then the
176 * key field (of key_length bytes) contains the key in encrypted form;
177 * if packet body length = 44, key field is absent and key_length
178 * represents the number of least significant octets from
179 * MS-MPPE-Send-Key attribute to be used as the keying material;
180 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
185 #endif /* _MSC_VER */
188 static void eapol_sm_txLogoff(struct eapol_sm *sm);
189 static void eapol_sm_txStart(struct eapol_sm *sm);
190 static void eapol_sm_processKey(struct eapol_sm *sm);
191 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
192 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
193 static void eapol_sm_abortSupp(struct eapol_sm *sm);
194 static void eapol_sm_abort_cached(struct eapol_sm *sm);
195 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
198 /* Port Timers state machine - implemented as a function that will be called
199 * once a second as a registered event loop timeout */
200 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
202 struct eapol_sm *sm = timeout_ctx;
204 if (sm->authWhile > 0) {
206 if (sm->authWhile == 0)
207 wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
209 if (sm->heldWhile > 0) {
211 if (sm->heldWhile == 0)
212 wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
214 if (sm->startWhen > 0) {
216 if (sm->startWhen == 0)
217 wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
219 if (sm->idleWhile > 0) {
221 if (sm->idleWhile == 0)
222 wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
225 if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
226 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
229 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
230 sm->timer_tick_enabled = 0;
236 static void eapol_enable_timer_tick(struct eapol_sm *sm)
238 if (sm->timer_tick_enabled)
240 wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
241 sm->timer_tick_enabled = 1;
242 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
243 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
247 SM_STATE(SUPP_PAE, LOGOFF)
249 SM_ENTRY(SUPP_PAE, LOGOFF);
250 eapol_sm_txLogoff(sm);
251 sm->logoffSent = TRUE;
252 sm->suppPortStatus = Unauthorized;
256 SM_STATE(SUPP_PAE, DISCONNECTED)
258 SM_ENTRY(SUPP_PAE, DISCONNECTED);
259 sm->sPortMode = Auto;
261 sm->logoffSent = FALSE;
262 sm->suppPortStatus = Unauthorized;
263 sm->suppAbort = TRUE;
265 sm->unicast_key_received = FALSE;
266 sm->broadcast_key_received = FALSE;
270 SM_STATE(SUPP_PAE, CONNECTING)
272 int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
273 SM_ENTRY(SUPP_PAE, CONNECTING);
275 sm->startWhen = sm->startPeriod;
279 * Do not send EAPOL-Start immediately since in most cases,
280 * Authenticator is going to start authentication immediately
281 * after association and an extra EAPOL-Start is just going to
282 * delay authentication. Use a short timeout to send the first
283 * EAPOL-Start if Authenticator does not start authentication.
286 /* Reduce latency on starting WPS negotiation. */
288 #else /* CONFIG_WPS */
290 #endif /* CONFIG_WPS */
292 eapol_enable_timer_tick(sm);
293 sm->eapolEap = FALSE;
295 eapol_sm_txStart(sm);
299 SM_STATE(SUPP_PAE, AUTHENTICATING)
301 SM_ENTRY(SUPP_PAE, AUTHENTICATING);
303 sm->suppSuccess = FALSE;
304 sm->suppFail = FALSE;
305 sm->suppTimeout = FALSE;
308 sm->suppStart = TRUE;
312 SM_STATE(SUPP_PAE, HELD)
314 SM_ENTRY(SUPP_PAE, HELD);
315 sm->heldWhile = sm->heldPeriod;
316 eapol_enable_timer_tick(sm);
317 sm->suppPortStatus = Unauthorized;
318 sm->cb_status = EAPOL_CB_FAILURE;
322 SM_STATE(SUPP_PAE, AUTHENTICATED)
324 SM_ENTRY(SUPP_PAE, AUTHENTICATED);
325 sm->suppPortStatus = Authorized;
326 sm->cb_status = EAPOL_CB_SUCCESS;
330 SM_STATE(SUPP_PAE, RESTART)
332 SM_ENTRY(SUPP_PAE, RESTART);
333 sm->eapRestart = TRUE;
337 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
339 SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
340 sm->suppPortStatus = Authorized;
341 sm->sPortMode = ForceAuthorized;
345 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
347 SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
348 sm->suppPortStatus = Unauthorized;
349 sm->sPortMode = ForceUnauthorized;
350 eapol_sm_txLogoff(sm);
356 if ((sm->userLogoff && !sm->logoffSent) &&
357 !(sm->initialize || !sm->portEnabled))
358 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
359 else if (((sm->portControl == Auto) &&
360 (sm->sPortMode != sm->portControl)) ||
361 sm->initialize || !sm->portEnabled)
362 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
363 else if ((sm->portControl == ForceAuthorized) &&
364 (sm->sPortMode != sm->portControl) &&
365 !(sm->initialize || !sm->portEnabled))
366 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
367 else if ((sm->portControl == ForceUnauthorized) &&
368 (sm->sPortMode != sm->portControl) &&
369 !(sm->initialize || !sm->portEnabled))
370 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
371 else switch (sm->SUPP_PAE_state) {
372 case SUPP_PAE_UNKNOWN:
374 case SUPP_PAE_LOGOFF:
376 SM_ENTER(SUPP_PAE, DISCONNECTED);
378 case SUPP_PAE_DISCONNECTED:
379 SM_ENTER(SUPP_PAE, CONNECTING);
381 case SUPP_PAE_CONNECTING:
382 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
383 SM_ENTER(SUPP_PAE, CONNECTING);
384 else if (sm->startWhen == 0 &&
385 sm->startCount >= sm->maxStart &&
387 SM_ENTER(SUPP_PAE, AUTHENTICATED);
388 else if (sm->eapSuccess || sm->eapFail)
389 SM_ENTER(SUPP_PAE, AUTHENTICATING);
390 else if (sm->eapolEap)
391 SM_ENTER(SUPP_PAE, RESTART);
392 else if (sm->startWhen == 0 &&
393 sm->startCount >= sm->maxStart &&
395 SM_ENTER(SUPP_PAE, HELD);
397 case SUPP_PAE_AUTHENTICATING:
398 if (sm->eapSuccess && !sm->portValid &&
399 sm->conf.accept_802_1x_keys &&
400 sm->conf.required_keys == 0) {
401 wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
402 "plaintext connection; no EAPOL-Key frames "
404 sm->portValid = TRUE;
405 if (sm->ctx->eapol_done_cb)
406 sm->ctx->eapol_done_cb(sm->ctx->ctx);
408 if (sm->eapSuccess && sm->portValid)
409 SM_ENTER(SUPP_PAE, AUTHENTICATED);
410 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
411 SM_ENTER(SUPP_PAE, HELD);
412 else if (sm->suppTimeout)
413 SM_ENTER(SUPP_PAE, CONNECTING);
416 if (sm->heldWhile == 0)
417 SM_ENTER(SUPP_PAE, CONNECTING);
418 else if (sm->eapolEap)
419 SM_ENTER(SUPP_PAE, RESTART);
421 case SUPP_PAE_AUTHENTICATED:
422 if (sm->eapolEap && sm->portValid)
423 SM_ENTER(SUPP_PAE, RESTART);
424 else if (!sm->portValid)
425 SM_ENTER(SUPP_PAE, DISCONNECTED);
427 case SUPP_PAE_RESTART:
429 SM_ENTER(SUPP_PAE, AUTHENTICATING);
431 case SUPP_PAE_S_FORCE_AUTH:
433 case SUPP_PAE_S_FORCE_UNAUTH:
439 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
441 SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
445 SM_STATE(KEY_RX, KEY_RECEIVE)
447 SM_ENTRY(KEY_RX, KEY_RECEIVE);
448 eapol_sm_processKey(sm);
455 if (sm->initialize || !sm->portEnabled)
456 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
457 switch (sm->KEY_RX_state) {
460 case KEY_RX_NO_KEY_RECEIVE:
462 SM_ENTER(KEY_RX, KEY_RECEIVE);
464 case KEY_RX_KEY_RECEIVE:
466 SM_ENTER(KEY_RX, KEY_RECEIVE);
472 SM_STATE(SUPP_BE, REQUEST)
474 SM_ENTRY(SUPP_BE, REQUEST);
477 eapol_sm_getSuppRsp(sm);
481 SM_STATE(SUPP_BE, RESPONSE)
483 SM_ENTRY(SUPP_BE, RESPONSE);
484 eapol_sm_txSuppRsp(sm);
489 SM_STATE(SUPP_BE, SUCCESS)
491 SM_ENTRY(SUPP_BE, SUCCESS);
493 sm->suppSuccess = TRUE;
495 if (eap_key_available(sm->eap)) {
496 /* New key received - clear IEEE 802.1X EAPOL-Key replay
498 sm->replay_counter_valid = FALSE;
503 SM_STATE(SUPP_BE, FAIL)
505 SM_ENTRY(SUPP_BE, FAIL);
510 SM_STATE(SUPP_BE, TIMEOUT)
512 SM_ENTRY(SUPP_BE, TIMEOUT);
513 sm->suppTimeout = TRUE;
517 SM_STATE(SUPP_BE, IDLE)
519 SM_ENTRY(SUPP_BE, IDLE);
520 sm->suppStart = FALSE;
521 sm->initial_req = TRUE;
525 SM_STATE(SUPP_BE, INITIALIZE)
527 SM_ENTRY(SUPP_BE, INITIALIZE);
528 eapol_sm_abortSupp(sm);
529 sm->suppAbort = FALSE;
533 SM_STATE(SUPP_BE, RECEIVE)
535 SM_ENTRY(SUPP_BE, RECEIVE);
536 sm->authWhile = sm->authPeriod;
537 eapol_enable_timer_tick(sm);
538 sm->eapolEap = FALSE;
539 sm->eapNoResp = FALSE;
540 sm->initial_req = FALSE;
546 if (sm->initialize || sm->suppAbort)
547 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
548 else switch (sm->SUPP_BE_state) {
549 case SUPP_BE_UNKNOWN:
551 case SUPP_BE_REQUEST:
553 * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
554 * and SUCCESS based on eapFail and eapSuccess, respectively.
555 * However, IEEE Std 802.1X-2004 is also specifying that
556 * eapNoResp should be set in conjuction with eapSuccess and
557 * eapFail which would mean that more than one of the
558 * transitions here would be activated at the same time.
559 * Skipping RESPONSE and/or RECEIVE states in these cases can
560 * cause problems and the direct transitions to do not seem
561 * correct. Because of this, the conditions for these
562 * transitions are verified only after eapNoResp. They are
563 * unlikely to be used since eapNoResp should always be set if
564 * either of eapSuccess or eapFail is set.
566 if (sm->eapResp && sm->eapNoResp) {
567 wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
568 "eapResp and eapNoResp set?!");
571 SM_ENTER(SUPP_BE, RESPONSE);
572 else if (sm->eapNoResp)
573 SM_ENTER(SUPP_BE, RECEIVE);
574 else if (sm->eapFail)
575 SM_ENTER(SUPP_BE, FAIL);
576 else if (sm->eapSuccess)
577 SM_ENTER(SUPP_BE, SUCCESS);
579 case SUPP_BE_RESPONSE:
580 SM_ENTER(SUPP_BE, RECEIVE);
582 case SUPP_BE_SUCCESS:
583 SM_ENTER(SUPP_BE, IDLE);
586 SM_ENTER(SUPP_BE, IDLE);
588 case SUPP_BE_TIMEOUT:
589 SM_ENTER(SUPP_BE, IDLE);
592 if (sm->eapFail && sm->suppStart)
593 SM_ENTER(SUPP_BE, FAIL);
594 else if (sm->eapolEap && sm->suppStart)
595 SM_ENTER(SUPP_BE, REQUEST);
596 else if (sm->eapSuccess && sm->suppStart)
597 SM_ENTER(SUPP_BE, SUCCESS);
599 case SUPP_BE_INITIALIZE:
600 SM_ENTER(SUPP_BE, IDLE);
602 case SUPP_BE_RECEIVE:
604 SM_ENTER(SUPP_BE, REQUEST);
605 else if (sm->eapFail)
606 SM_ENTER(SUPP_BE, FAIL);
607 else if (sm->authWhile == 0)
608 SM_ENTER(SUPP_BE, TIMEOUT);
609 else if (sm->eapSuccess)
610 SM_ENTER(SUPP_BE, SUCCESS);
616 static void eapol_sm_txLogoff(struct eapol_sm *sm)
618 wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
619 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
620 IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
621 sm->dot1xSuppEapolLogoffFramesTx++;
622 sm->dot1xSuppEapolFramesTx++;
626 static void eapol_sm_txStart(struct eapol_sm *sm)
628 wpa_printf(MSG_DEBUG, "EAPOL: txStart");
629 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
630 IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
631 sm->dot1xSuppEapolStartFramesTx++;
632 sm->dot1xSuppEapolFramesTx++;
636 #define IEEE8021X_ENCR_KEY_LEN 32
637 #define IEEE8021X_SIGN_KEY_LEN 32
639 struct eap_key_data {
640 u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
641 u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
645 static void eapol_sm_processKey(struct eapol_sm *sm)
647 struct ieee802_1x_hdr *hdr;
648 struct ieee802_1x_eapol_key *key;
649 struct eap_key_data keydata;
650 u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
651 u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
652 int key_len, res, sign_key_len, encr_key_len;
655 wpa_printf(MSG_DEBUG, "EAPOL: processKey");
656 if (sm->last_rx_key == NULL)
659 if (!sm->conf.accept_802_1x_keys) {
660 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
661 " even though this was not accepted - "
662 "ignoring this packet");
666 hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
667 key = (struct ieee802_1x_eapol_key *) (hdr + 1);
668 if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) {
669 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
672 rx_key_length = WPA_GET_BE16(key->key_length);
673 wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
674 "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
675 hdr->version, hdr->type, be_to_host16(hdr->length),
676 key->type, rx_key_length, key->key_index);
678 eapol_sm_notify_lower_layer_success(sm, 1);
679 sign_key_len = IEEE8021X_SIGN_KEY_LEN;
680 encr_key_len = IEEE8021X_ENCR_KEY_LEN;
681 res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
683 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
684 "decrypting EAPOL-Key keys");
688 /* LEAP derives only 16 bytes of keying material. */
689 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
691 wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
692 "master key for decrypting EAPOL-Key keys");
697 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
699 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
700 "data for decrypting EAPOL-Key keys (res=%d)", res);
704 /* The key replay_counter must increase when same master key */
705 if (sm->replay_counter_valid &&
706 os_memcmp(sm->last_replay_counter, key->replay_counter,
707 IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
708 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
709 "not increase - ignoring key");
710 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
711 sm->last_replay_counter,
712 IEEE8021X_REPLAY_COUNTER_LEN);
713 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
714 key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
718 /* Verify key signature (HMAC-MD5) */
719 os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
720 os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
721 hmac_md5(keydata.sign_key, sign_key_len,
722 sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
724 if (os_memcmp(orig_key_sign, key->key_signature,
725 IEEE8021X_KEY_SIGN_LEN) != 0) {
726 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
728 os_memcpy(key->key_signature, orig_key_sign,
729 IEEE8021X_KEY_SIGN_LEN);
732 wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
734 key_len = be_to_host16(hdr->length) - sizeof(*key);
735 if (key_len > 32 || rx_key_length > 32) {
736 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
737 key_len ? key_len : rx_key_length);
740 if (key_len == rx_key_length) {
741 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
742 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
744 os_memcpy(datakey, key + 1, key_len);
745 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
747 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
749 } else if (key_len == 0) {
751 * IEEE 802.1X-2004 specifies that least significant Key Length
752 * octets from MS-MPPE-Send-Key are used as the key if the key
753 * data is not present. This seems to be meaning the beginning
754 * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
755 * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
756 * Anyway, taking the beginning of the keying material from EAP
757 * seems to interoperate with Authenticators.
759 key_len = rx_key_length;
760 os_memcpy(datakey, keydata.encr_key, key_len);
761 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
762 "material data encryption key",
765 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
766 "(key_length=%d)", key_len, rx_key_length);
770 sm->replay_counter_valid = TRUE;
771 os_memcpy(sm->last_replay_counter, key->replay_counter,
772 IEEE8021X_REPLAY_COUNTER_LEN);
774 wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
776 key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
777 "unicast" : "broadcast",
778 key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
780 if (sm->ctx->set_wep_key &&
781 sm->ctx->set_wep_key(sm->ctx->ctx,
782 key->key_index & IEEE8021X_KEY_INDEX_FLAG,
783 key->key_index & IEEE8021X_KEY_INDEX_MASK,
784 datakey, key_len) < 0) {
785 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
788 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
789 sm->unicast_key_received = TRUE;
791 sm->broadcast_key_received = TRUE;
793 if ((sm->unicast_key_received ||
794 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
795 (sm->broadcast_key_received ||
796 !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
798 wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
800 sm->portValid = TRUE;
801 if (sm->ctx->eapol_done_cb)
802 sm->ctx->eapol_done_cb(sm->ctx->ctx);
808 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
810 wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
811 /* EAP layer processing; no special code is needed, since Supplicant
812 * Backend state machine is waiting for eapNoResp or eapResp to be set
813 * and these are only set in the EAP state machine when the processing
818 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
822 wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
823 resp = eap_get_eapRespData(sm->eap);
825 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
830 /* Send EAP-Packet from the EAP layer to the Authenticator */
831 sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
832 IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
835 /* eapRespData is not used anymore, so free it here */
839 sm->dot1xSuppEapolReqIdFramesRx++;
841 sm->dot1xSuppEapolReqFramesRx++;
842 sm->dot1xSuppEapolRespFramesTx++;
843 sm->dot1xSuppEapolFramesTx++;
847 static void eapol_sm_abortSupp(struct eapol_sm *sm)
849 /* release system resources that may have been allocated for the
850 * authentication session */
851 os_free(sm->last_rx_key);
852 sm->last_rx_key = NULL;
853 wpabuf_free(sm->eapReqData);
854 sm->eapReqData = NULL;
855 eap_sm_abort(sm->eap);
859 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
861 eapol_sm_step(timeout_ctx);
866 * eapol_sm_step - EAPOL state machine step function
867 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
869 * This function is called to notify the state machine about changed external
870 * variables. It will step through the EAPOL state machines in loop to process
871 * all triggered state changes.
873 void eapol_sm_step(struct eapol_sm *sm)
877 /* In theory, it should be ok to run this in loop until !changed.
878 * However, it is better to use a limit on number of iterations to
879 * allow events (e.g., SIGTERM) to stop the program cleanly if the
880 * state machine were to generate a busy loop. */
881 for (i = 0; i < 100; i++) {
883 SM_STEP_RUN(SUPP_PAE);
885 SM_STEP_RUN(SUPP_BE);
886 if (eap_peer_sm_step(sm->eap))
893 /* restart EAPOL state machine step from timeout call in order
894 * to allow other events to be processed. */
895 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
896 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
899 if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
900 int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;
901 sm->cb_status = EAPOL_CB_IN_PROGRESS;
902 sm->ctx->cb(sm, success, sm->ctx->cb_ctx);
907 #ifdef CONFIG_CTRL_IFACE
908 static const char *eapol_supp_pae_state(int state)
911 case SUPP_PAE_LOGOFF:
913 case SUPP_PAE_DISCONNECTED:
914 return "DISCONNECTED";
915 case SUPP_PAE_CONNECTING:
917 case SUPP_PAE_AUTHENTICATING:
918 return "AUTHENTICATING";
921 case SUPP_PAE_AUTHENTICATED:
922 return "AUTHENTICATED";
923 case SUPP_PAE_RESTART:
931 static const char *eapol_supp_be_state(int state)
934 case SUPP_BE_REQUEST:
936 case SUPP_BE_RESPONSE:
938 case SUPP_BE_SUCCESS:
942 case SUPP_BE_TIMEOUT:
946 case SUPP_BE_INITIALIZE:
948 case SUPP_BE_RECEIVE:
956 static const char * eapol_port_status(PortStatus status)
958 if (status == Authorized)
961 return "Unauthorized";
963 #endif /* CONFIG_CTRL_IFACE */
966 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
967 static const char * eapol_port_control(PortControl ctrl)
972 case ForceUnauthorized:
973 return "ForceUnauthorized";
974 case ForceAuthorized:
975 return "ForceAuthorized";
980 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
984 * eapol_sm_configure - Set EAPOL variables
985 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
986 * @heldPeriod: dot1xSuppHeldPeriod
987 * @authPeriod: dot1xSuppAuthPeriod
988 * @startPeriod: dot1xSuppStartPeriod
989 * @maxStart: dot1xSuppMaxStart
991 * Set configurable EAPOL state machine variables. Each variable can be set to
992 * the given value or ignored if set to -1 (to set only some of the variables).
994 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
995 int startPeriod, int maxStart)
1000 sm->heldPeriod = heldPeriod;
1001 if (authPeriod >= 0)
1002 sm->authPeriod = authPeriod;
1003 if (startPeriod >= 0)
1004 sm->startPeriod = startPeriod;
1006 sm->maxStart = maxStart;
1010 #ifdef CONFIG_CTRL_IFACE
1012 * eapol_sm_get_status - Get EAPOL state machine status
1013 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1014 * @buf: Buffer for status information
1015 * @buflen: Maximum buffer length
1016 * @verbose: Whether to include verbose status information
1017 * Returns: Number of bytes written to buf.
1019 * Query EAPOL state machine for status information. This function fills in a
1020 * text area with current status information from the EAPOL state machine. If
1021 * the buffer (buf) is not large enough, status information will be truncated
1022 * to fit the buffer.
1024 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1031 len = os_snprintf(buf, buflen,
1032 "Supplicant PAE state=%s\n"
1033 "suppPortStatus=%s\n",
1034 eapol_supp_pae_state(sm->SUPP_PAE_state),
1035 eapol_port_status(sm->suppPortStatus));
1036 if (len < 0 || (size_t) len >= buflen)
1040 ret = os_snprintf(buf + len, buflen - len,
1046 "Supplicant Backend state=%s\n",
1051 eapol_port_control(sm->portControl),
1052 eapol_supp_be_state(sm->SUPP_BE_state));
1053 if (ret < 0 || (size_t) ret >= buflen - len)
1058 len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1065 * eapol_sm_get_mib - Get EAPOL state machine MIBs
1066 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1067 * @buf: Buffer for MIB information
1068 * @buflen: Maximum buffer length
1069 * Returns: Number of bytes written to buf.
1071 * Query EAPOL state machine for MIB information. This function fills in a
1072 * text area with current MIB information from the EAPOL state machine. If
1073 * the buffer (buf) is not large enough, MIB information will be truncated to
1076 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1083 ret = os_snprintf(buf, buflen,
1084 "dot1xSuppPaeState=%d\n"
1085 "dot1xSuppHeldPeriod=%u\n"
1086 "dot1xSuppAuthPeriod=%u\n"
1087 "dot1xSuppStartPeriod=%u\n"
1088 "dot1xSuppMaxStart=%u\n"
1089 "dot1xSuppSuppControlledPortStatus=%s\n"
1090 "dot1xSuppBackendPaeState=%d\n",
1096 sm->suppPortStatus == Authorized ?
1097 "Authorized" : "Unauthorized",
1100 if (ret < 0 || (size_t) ret >= buflen)
1104 ret = os_snprintf(buf + len, buflen - len,
1105 "dot1xSuppEapolFramesRx=%u\n"
1106 "dot1xSuppEapolFramesTx=%u\n"
1107 "dot1xSuppEapolStartFramesTx=%u\n"
1108 "dot1xSuppEapolLogoffFramesTx=%u\n"
1109 "dot1xSuppEapolRespFramesTx=%u\n"
1110 "dot1xSuppEapolReqIdFramesRx=%u\n"
1111 "dot1xSuppEapolReqFramesRx=%u\n"
1112 "dot1xSuppInvalidEapolFramesRx=%u\n"
1113 "dot1xSuppEapLengthErrorFramesRx=%u\n"
1114 "dot1xSuppLastEapolFrameVersion=%u\n"
1115 "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1116 sm->dot1xSuppEapolFramesRx,
1117 sm->dot1xSuppEapolFramesTx,
1118 sm->dot1xSuppEapolStartFramesTx,
1119 sm->dot1xSuppEapolLogoffFramesTx,
1120 sm->dot1xSuppEapolRespFramesTx,
1121 sm->dot1xSuppEapolReqIdFramesRx,
1122 sm->dot1xSuppEapolReqFramesRx,
1123 sm->dot1xSuppInvalidEapolFramesRx,
1124 sm->dot1xSuppEapLengthErrorFramesRx,
1125 sm->dot1xSuppLastEapolFrameVersion,
1126 MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1128 if (ret < 0 || (size_t) ret >= buflen - len)
1134 #endif /* CONFIG_CTRL_IFACE */
1138 * eapol_sm_rx_eapol - Process received EAPOL frames
1139 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1140 * @src: Source MAC address of the EAPOL packet
1141 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1142 * @len: Length of the EAPOL frame
1143 * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1146 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1149 const struct ieee802_1x_hdr *hdr;
1150 const struct ieee802_1x_eapol_key *key;
1157 sm->dot1xSuppEapolFramesRx++;
1158 if (len < sizeof(*hdr)) {
1159 sm->dot1xSuppInvalidEapolFramesRx++;
1162 hdr = (const struct ieee802_1x_hdr *) buf;
1163 sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1164 os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1165 if (hdr->version < EAPOL_VERSION) {
1166 /* TODO: backwards compatibility */
1168 plen = be_to_host16(hdr->length);
1169 if (plen > len - sizeof(*hdr)) {
1170 sm->dot1xSuppEapLengthErrorFramesRx++;
1174 if (sm->conf.workaround &&
1175 plen < len - sizeof(*hdr) &&
1176 hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1177 len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1178 const struct eap_hdr *ehdr =
1179 (const struct eap_hdr *) (hdr + 1);
1182 elen = be_to_host16(ehdr->length);
1183 if (elen > plen && elen <= len - sizeof(*hdr)) {
1185 * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1186 * packets with too short EAPOL header length field
1187 * (14 octets). This is fixed in firmware Ver.1.49.
1188 * As a workaround, fix the EAPOL header based on the
1189 * correct length in the EAP packet.
1191 wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1192 "payload length based on EAP header: "
1193 "%d -> %d", (int) plen, elen);
1197 #endif /* CONFIG_WPS */
1198 data_len = plen + sizeof(*hdr);
1200 switch (hdr->type) {
1201 case IEEE802_1X_TYPE_EAP_PACKET:
1202 if (sm->cached_pmk) {
1203 /* Trying to use PMKSA caching, but Authenticator did
1204 * not seem to have a matching entry. Need to restart
1205 * EAPOL state machines.
1207 eapol_sm_abort_cached(sm);
1209 wpabuf_free(sm->eapReqData);
1210 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1211 if (sm->eapReqData) {
1212 wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1214 sm->eapolEap = TRUE;
1218 case IEEE802_1X_TYPE_EAPOL_KEY:
1219 if (plen < sizeof(*key)) {
1220 wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1224 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1225 if (key->type == EAPOL_KEY_TYPE_WPA ||
1226 key->type == EAPOL_KEY_TYPE_RSN) {
1227 /* WPA Supplicant takes care of this frame. */
1228 wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1229 "frame in EAPOL state machines");
1233 if (key->type != EAPOL_KEY_TYPE_RC4) {
1234 wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1235 "EAPOL-Key type %d", key->type);
1238 os_free(sm->last_rx_key);
1239 sm->last_rx_key = os_malloc(data_len);
1240 if (sm->last_rx_key) {
1241 wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1243 os_memcpy(sm->last_rx_key, buf, data_len);
1244 sm->last_rx_key_len = data_len;
1250 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1252 sm->dot1xSuppInvalidEapolFramesRx++;
1261 * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1262 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1264 * Notify EAPOL state machine about transmitted EAPOL packet from an external
1265 * component, e.g., WPA. This will update the statistics.
1267 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1270 sm->dot1xSuppEapolFramesTx++;
1275 * eapol_sm_notify_portEnabled - Notification about portEnabled change
1276 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1277 * @enabled: New portEnabled value
1279 * Notify EAPOL state machine about new portEnabled value.
1281 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1285 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1286 "portEnabled=%d", enabled);
1287 sm->portEnabled = enabled;
1293 * eapol_sm_notify_portValid - Notification about portValid change
1294 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1295 * @valid: New portValid value
1297 * Notify EAPOL state machine about new portValid value.
1299 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1303 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1304 "portValid=%d", valid);
1305 sm->portValid = valid;
1311 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1312 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1313 * @success: %TRUE = set success, %FALSE = clear success
1315 * Notify the EAPOL state machine that external event has forced EAP state to
1316 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1318 * This function is called to update EAP state when WPA-PSK key handshake has
1319 * been completed successfully since WPA-PSK does not use EAP state machine.
1321 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1325 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1326 "EAP success=%d", success);
1327 sm->eapSuccess = success;
1328 sm->altAccept = success;
1330 eap_notify_success(sm->eap);
1336 * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1337 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1338 * @fail: %TRUE = set failure, %FALSE = clear failure
1340 * Notify EAPOL state machine that external event has forced EAP state to
1341 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1343 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1347 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1348 "EAP fail=%d", fail);
1350 sm->altReject = fail;
1356 * eapol_sm_notify_config - Notification of EAPOL configuration change
1357 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1358 * @config: Pointer to current network EAP configuration
1359 * @conf: Pointer to EAPOL configuration data
1361 * Notify EAPOL state machine that configuration has changed. config will be
1362 * stored as a backpointer to network configuration. This can be %NULL to clear
1363 * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1364 * data. If conf is %NULL, this part of the configuration change will be
1367 void eapol_sm_notify_config(struct eapol_sm *sm,
1368 struct eap_peer_config *config,
1369 const struct eapol_config *conf)
1374 sm->config = config;
1379 sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1380 sm->conf.required_keys = conf->required_keys;
1381 sm->conf.fast_reauth = conf->fast_reauth;
1382 sm->conf.workaround = conf->workaround;
1384 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1385 eap_set_workaround(sm->eap, conf->workaround);
1386 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1392 * eapol_sm_get_key - Get master session key (MSK) from EAP
1393 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1394 * @key: Pointer for key buffer
1395 * @len: Number of bytes to copy to key
1396 * Returns: 0 on success (len of key available), maximum available key len
1397 * (>0) if key is available but it is shorter than len, or -1 on failure.
1399 * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1400 * is available only after a successful authentication.
1402 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1407 if (sm == NULL || !eap_key_available(sm->eap)) {
1408 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1411 eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1412 if (eap_key == NULL) {
1413 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1416 if (len > eap_len) {
1417 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1418 "available (len=%lu)",
1419 (unsigned long) len, (unsigned long) eap_len);
1422 os_memcpy(key, eap_key, len);
1423 wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1424 (unsigned long) len);
1430 * eapol_sm_notify_logoff - Notification of logon/logoff commands
1431 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1432 * @logoff: Whether command was logoff
1434 * Notify EAPOL state machines that user requested logon/logoff.
1436 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1439 sm->userLogoff = logoff;
1446 * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1447 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1449 * Notify EAPOL state machines that PMKSA caching was successful. This is used
1450 * to move EAPOL and EAP state machines into authenticated/successful state.
1452 void eapol_sm_notify_cached(struct eapol_sm *sm)
1456 wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1457 sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED;
1458 sm->suppPortStatus = Authorized;
1459 sm->portValid = TRUE;
1460 eap_notify_success(sm->eap);
1466 * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1467 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1468 * @attempt: Whether PMKSA caching is tried
1470 * Notify EAPOL state machines whether PMKSA caching is used.
1472 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
1477 wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1478 sm->cached_pmk = TRUE;
1480 wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
1481 sm->cached_pmk = FALSE;
1486 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1488 wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1489 "doing full EAP authentication");
1492 sm->cached_pmk = FALSE;
1493 sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1494 sm->suppPortStatus = Unauthorized;
1496 /* Make sure we do not start sending EAPOL-Start frames first, but
1497 * instead move to RESTART state to start EAPOL authentication. */
1499 eapol_enable_timer_tick(sm);
1501 if (sm->ctx->aborted_cached)
1502 sm->ctx->aborted_cached(sm->ctx->ctx);
1507 * eapol_sm_register_scard_ctx - Notification of smart card context
1508 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1509 * @ctx: Context data for smart card operations
1511 * Notify EAPOL state machines of context data for smart card operations. This
1512 * context data will be used as a parameter for scard_*() functions.
1514 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1517 sm->ctx->scard_ctx = ctx;
1518 eap_register_scard_ctx(sm->eap, ctx);
1524 * eapol_sm_notify_portControl - Notification of portControl changes
1525 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1526 * @portControl: New value for portControl variable
1528 * Notify EAPOL state machines that portControl variable has changed.
1530 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1534 wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1535 "portControl=%s", eapol_port_control(portControl));
1536 sm->portControl = portControl;
1542 * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1543 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1545 * Notify EAPOL state machines that a monitor was attached to the control
1546 * interface to trigger re-sending of pending requests for user input.
1548 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1552 eap_sm_notify_ctrl_attached(sm->eap);
1557 * eapol_sm_notify_ctrl_response - Notification of received user input
1558 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1560 * Notify EAPOL state machines that a control response, i.e., user
1561 * input, was received in order to trigger retrying of a pending EAP request.
1563 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1567 if (sm->eapReqData && !sm->eapReq) {
1568 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1569 "input) notification - retrying pending EAP "
1571 sm->eapolEap = TRUE;
1579 * eapol_sm_request_reauth - Request reauthentication
1580 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1582 * This function can be used to request EAPOL reauthentication, e.g., when the
1583 * current PMKSA entry is nearing expiration.
1585 void eapol_sm_request_reauth(struct eapol_sm *sm)
1587 if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1589 eapol_sm_txStart(sm);
1594 * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1595 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1596 * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1597 * machine loop (eapol_sm_step())
1599 * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1600 * successful authentication. This is used to recover from dropped EAP-Success
1603 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1607 eap_notify_lower_layer_success(sm->eap);
1614 * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1615 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1617 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1620 eap_invalidate_cached_session(sm->eap);
1624 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1626 struct eapol_sm *sm = ctx;
1627 return sm ? sm->config : NULL;
1631 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1633 struct eapol_sm *sm = ctx;
1634 if (sm == NULL || sm->eapReqData == NULL)
1637 return sm->eapReqData;
1641 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1643 struct eapol_sm *sm = ctx;
1647 case EAPOL_eapSuccess:
1648 return sm->eapSuccess;
1649 case EAPOL_eapRestart:
1650 return sm->eapRestart;
1655 case EAPOL_eapNoResp:
1656 return sm->eapNoResp;
1659 case EAPOL_portEnabled:
1660 return sm->portEnabled;
1661 case EAPOL_altAccept:
1662 return sm->altAccept;
1663 case EAPOL_altReject:
1664 return sm->altReject;
1670 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1673 struct eapol_sm *sm = ctx;
1677 case EAPOL_eapSuccess:
1678 sm->eapSuccess = value;
1680 case EAPOL_eapRestart:
1681 sm->eapRestart = value;
1684 sm->eapFail = value;
1687 sm->eapResp = value;
1689 case EAPOL_eapNoResp:
1690 sm->eapNoResp = value;
1695 case EAPOL_portEnabled:
1696 sm->portEnabled = value;
1698 case EAPOL_altAccept:
1699 sm->altAccept = value;
1701 case EAPOL_altReject:
1702 sm->altReject = value;
1708 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1710 struct eapol_sm *sm = ctx;
1714 case EAPOL_idleWhile:
1715 return sm->idleWhile;
1721 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1724 struct eapol_sm *sm = ctx;
1728 case EAPOL_idleWhile:
1729 sm->idleWhile = value;
1730 eapol_enable_timer_tick(sm);
1736 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1738 #ifndef CONFIG_NO_CONFIG_BLOBS
1739 struct eapol_sm *sm = ctx;
1740 if (sm && sm->ctx && sm->ctx->set_config_blob)
1741 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1742 #endif /* CONFIG_NO_CONFIG_BLOBS */
1746 static const struct wpa_config_blob *
1747 eapol_sm_get_config_blob(void *ctx, const char *name)
1749 #ifndef CONFIG_NO_CONFIG_BLOBS
1750 struct eapol_sm *sm = ctx;
1751 if (sm && sm->ctx && sm->ctx->get_config_blob)
1752 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1755 #else /* CONFIG_NO_CONFIG_BLOBS */
1757 #endif /* CONFIG_NO_CONFIG_BLOBS */
1761 static void eapol_sm_notify_pending(void *ctx)
1763 struct eapol_sm *sm = ctx;
1766 if (sm->eapReqData && !sm->eapReq) {
1767 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1768 "state machine - retrying pending EAP Request");
1769 sm->eapolEap = TRUE;
1776 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1777 static void eapol_sm_eap_param_needed(void *ctx, const char *field,
1780 struct eapol_sm *sm = ctx;
1781 wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1782 if (sm->ctx->eap_param_needed)
1783 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1785 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1786 #define eapol_sm_eap_param_needed NULL
1787 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1790 static struct eapol_callbacks eapol_cb =
1792 eapol_sm_get_config,
1797 eapol_sm_get_eapReqData,
1798 eapol_sm_set_config_blob,
1799 eapol_sm_get_config_blob,
1800 eapol_sm_notify_pending,
1801 eapol_sm_eap_param_needed
1806 * eapol_sm_init - Initialize EAPOL state machine
1807 * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
1808 * and EAPOL state machine will free it in eapol_sm_deinit()
1809 * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
1811 * Allocate and initialize an EAPOL state machine.
1813 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
1815 struct eapol_sm *sm;
1816 struct eap_config conf;
1817 sm = os_zalloc(sizeof(*sm));
1822 sm->portControl = Auto;
1824 /* Supplicant PAE state machine */
1825 sm->heldPeriod = 60;
1826 sm->startPeriod = 30;
1829 /* Supplicant Backend state machine */
1830 sm->authPeriod = 30;
1832 os_memset(&conf, 0, sizeof(conf));
1833 #ifdef EAP_TLS_OPENSSL
1834 conf.opensc_engine_path = ctx->opensc_engine_path;
1835 conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
1836 conf.pkcs11_module_path = ctx->pkcs11_module_path;
1837 #endif /* EAP_TLS_OPENSSL */
1838 conf.wps = ctx->wps;
1840 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
1841 if (sm->eap == NULL) {
1846 /* Initialize EAPOL state machines */
1847 sm->initialize = TRUE;
1849 sm->initialize = FALSE;
1852 sm->timer_tick_enabled = 1;
1853 eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
1860 * eapol_sm_deinit - Deinitialize EAPOL state machine
1861 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1863 * Deinitialize and free EAPOL state machine.
1865 void eapol_sm_deinit(struct eapol_sm *sm)
1869 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
1870 eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
1871 eap_peer_sm_deinit(sm->eap);
1872 os_free(sm->last_rx_key);
1873 wpabuf_free(sm->eapReqData);