]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - src/eapol_supp/eapol_supp_sm.c
Import wpa_supplicant/hostapd 2.7
[FreeBSD/FreeBSD.git] / src / eapol_supp / eapol_supp_sm.c
1 /*
2  * EAPOL supplicant state machines
3  * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "state_machine.h"
13 #include "wpabuf.h"
14 #include "eloop.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_config.h"
20 #include "eap_peer/eap_proxy.h"
21 #include "eapol_supp_sm.h"
22
23 #define STATE_MACHINE_DATA struct eapol_sm
24 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
25
26
27 /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
28
29 /**
30  * struct eapol_sm - Internal data for EAPOL state machines
31  */
32 struct eapol_sm {
33         /* Timers */
34         unsigned int authWhile;
35         unsigned int heldWhile;
36         unsigned int startWhen;
37         unsigned int idleWhile; /* for EAP state machine */
38         int timer_tick_enabled;
39
40         /* Global variables */
41         Boolean eapFail;
42         Boolean eapolEap;
43         Boolean eapSuccess;
44         Boolean initialize;
45         Boolean keyDone;
46         Boolean keyRun;
47         PortControl portControl;
48         Boolean portEnabled;
49         PortStatus suppPortStatus;  /* dot1xSuppControlledPortStatus */
50         Boolean portValid;
51         Boolean suppAbort;
52         Boolean suppFail;
53         Boolean suppStart;
54         Boolean suppSuccess;
55         Boolean suppTimeout;
56
57         /* Supplicant PAE state machine */
58         enum {
59                 SUPP_PAE_UNKNOWN = 0,
60                 SUPP_PAE_DISCONNECTED = 1,
61                 SUPP_PAE_LOGOFF = 2,
62                 SUPP_PAE_CONNECTING = 3,
63                 SUPP_PAE_AUTHENTICATING = 4,
64                 SUPP_PAE_AUTHENTICATED = 5,
65                 /* unused(6) */
66                 SUPP_PAE_HELD = 7,
67                 SUPP_PAE_RESTART = 8,
68                 SUPP_PAE_S_FORCE_AUTH = 9,
69                 SUPP_PAE_S_FORCE_UNAUTH = 10
70         } SUPP_PAE_state; /* dot1xSuppPaeState */
71         /* Variables */
72         Boolean userLogoff;
73         Boolean logoffSent;
74         unsigned int startCount;
75         Boolean eapRestart;
76         PortControl sPortMode;
77         /* Constants */
78         unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
79         unsigned int startPeriod; /* dot1xSuppStartPeriod */
80         unsigned int maxStart; /* dot1xSuppMaxStart */
81
82         /* Key Receive state machine */
83         enum {
84                 KEY_RX_UNKNOWN = 0,
85                 KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
86         } KEY_RX_state;
87         /* Variables */
88         Boolean rxKey;
89
90         /* Supplicant Backend state machine */
91         enum {
92                 SUPP_BE_UNKNOWN = 0,
93                 SUPP_BE_INITIALIZE = 1,
94                 SUPP_BE_IDLE = 2,
95                 SUPP_BE_REQUEST = 3,
96                 SUPP_BE_RECEIVE = 4,
97                 SUPP_BE_RESPONSE = 5,
98                 SUPP_BE_FAIL = 6,
99                 SUPP_BE_TIMEOUT = 7,
100                 SUPP_BE_SUCCESS = 8
101         } SUPP_BE_state; /* dot1xSuppBackendPaeState */
102         /* Variables */
103         Boolean eapNoResp;
104         Boolean eapReq;
105         Boolean eapResp;
106         /* Constants */
107         unsigned int authPeriod; /* dot1xSuppAuthPeriod */
108
109         /* Statistics */
110         unsigned int dot1xSuppEapolFramesRx;
111         unsigned int dot1xSuppEapolFramesTx;
112         unsigned int dot1xSuppEapolStartFramesTx;
113         unsigned int dot1xSuppEapolLogoffFramesTx;
114         unsigned int dot1xSuppEapolRespFramesTx;
115         unsigned int dot1xSuppEapolReqIdFramesRx;
116         unsigned int dot1xSuppEapolReqFramesRx;
117         unsigned int dot1xSuppInvalidEapolFramesRx;
118         unsigned int dot1xSuppEapLengthErrorFramesRx;
119         unsigned int dot1xSuppLastEapolFrameVersion;
120         unsigned char dot1xSuppLastEapolFrameSource[6];
121
122         /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
123         Boolean changed;
124         struct eap_sm *eap;
125         struct eap_peer_config *config;
126         Boolean initial_req;
127         u8 *last_rx_key;
128         size_t last_rx_key_len;
129         struct wpabuf *eapReqData; /* for EAP */
130         Boolean altAccept; /* for EAP */
131         Boolean altReject; /* for EAP */
132         Boolean eapTriggerStart;
133         Boolean replay_counter_valid;
134         u8 last_replay_counter[16];
135         struct eapol_config conf;
136         struct eapol_ctx *ctx;
137         enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
138                 cb_status;
139         Boolean cached_pmk;
140
141         Boolean unicast_key_received, broadcast_key_received;
142
143         Boolean force_authorized_update;
144
145 #ifdef CONFIG_EAP_PROXY
146         Boolean use_eap_proxy;
147         struct eap_proxy_sm *eap_proxy;
148 #endif /* CONFIG_EAP_PROXY */
149 };
150
151
152 static void eapol_sm_txLogoff(struct eapol_sm *sm);
153 static void eapol_sm_txStart(struct eapol_sm *sm);
154 static void eapol_sm_processKey(struct eapol_sm *sm);
155 static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
156 static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
157 static void eapol_sm_abortSupp(struct eapol_sm *sm);
158 static void eapol_sm_abort_cached(struct eapol_sm *sm);
159 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
160 static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
161 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
162
163
164 /* Port Timers state machine - implemented as a function that will be called
165  * once a second as a registered event loop timeout */
166 static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
167 {
168         struct eapol_sm *sm = timeout_ctx;
169
170         if (sm->authWhile > 0) {
171                 sm->authWhile--;
172                 if (sm->authWhile == 0)
173                         wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
174         }
175         if (sm->heldWhile > 0) {
176                 sm->heldWhile--;
177                 if (sm->heldWhile == 0)
178                         wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
179         }
180         if (sm->startWhen > 0) {
181                 sm->startWhen--;
182                 if (sm->startWhen == 0)
183                         wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
184         }
185         if (sm->idleWhile > 0) {
186                 sm->idleWhile--;
187                 if (sm->idleWhile == 0)
188                         wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
189         }
190
191         if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
192                 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
193                                        sm);
194         } else {
195                 wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
196                 sm->timer_tick_enabled = 0;
197         }
198         eapol_sm_step(sm);
199 }
200
201
202 static void eapol_enable_timer_tick(struct eapol_sm *sm)
203 {
204         if (sm->timer_tick_enabled)
205                 return;
206         wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
207         sm->timer_tick_enabled = 1;
208         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
209         eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
210 }
211
212
213 SM_STATE(SUPP_PAE, LOGOFF)
214 {
215         SM_ENTRY(SUPP_PAE, LOGOFF);
216         eapol_sm_txLogoff(sm);
217         sm->logoffSent = TRUE;
218         eapol_sm_set_port_unauthorized(sm);
219 }
220
221
222 SM_STATE(SUPP_PAE, DISCONNECTED)
223 {
224         SM_ENTRY(SUPP_PAE, DISCONNECTED);
225         sm->sPortMode = Auto;
226         sm->startCount = 0;
227         sm->eapTriggerStart = FALSE;
228         sm->logoffSent = FALSE;
229         eapol_sm_set_port_unauthorized(sm);
230         sm->suppAbort = TRUE;
231
232         sm->unicast_key_received = FALSE;
233         sm->broadcast_key_received = FALSE;
234
235         /*
236          * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so
237          * allows the timer tick to be stopped more quickly when the port is
238          * not enabled. Since this variable is used only within HELD state,
239          * clearing it on initialization does not change actual state machine
240          * behavior.
241          */
242         sm->heldWhile = 0;
243 }
244
245
246 SM_STATE(SUPP_PAE, CONNECTING)
247 {
248         int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING ||
249                 sm->SUPP_PAE_state == SUPP_PAE_HELD;
250         SM_ENTRY(SUPP_PAE, CONNECTING);
251
252         if (sm->eapTriggerStart)
253                 send_start = 1;
254         if (sm->ctx->preauth)
255                 send_start = 1;
256         sm->eapTriggerStart = FALSE;
257
258         if (send_start) {
259                 sm->startWhen = sm->startPeriod;
260                 sm->startCount++;
261         } else {
262                 /*
263                  * Do not send EAPOL-Start immediately since in most cases,
264                  * Authenticator is going to start authentication immediately
265                  * after association and an extra EAPOL-Start is just going to
266                  * delay authentication. Use a short timeout to send the first
267                  * EAPOL-Start if Authenticator does not start authentication.
268                  */
269                 if (sm->conf.wps && !(sm->conf.wps & EAPOL_PEER_IS_WPS20_AP)) {
270                         /* Reduce latency on starting WPS negotiation. */
271                         wpa_printf(MSG_DEBUG,
272                                    "EAPOL: Using shorter startWhen for WPS");
273                         sm->startWhen = 1;
274                 } else {
275                         sm->startWhen = 2;
276                 }
277         }
278         eapol_enable_timer_tick(sm);
279         sm->eapolEap = FALSE;
280         if (send_start)
281                 eapol_sm_txStart(sm);
282 }
283
284
285 SM_STATE(SUPP_PAE, AUTHENTICATING)
286 {
287         SM_ENTRY(SUPP_PAE, AUTHENTICATING);
288         sm->startCount = 0;
289         sm->suppSuccess = FALSE;
290         sm->suppFail = FALSE;
291         sm->suppTimeout = FALSE;
292         sm->keyRun = FALSE;
293         sm->keyDone = FALSE;
294         sm->suppStart = TRUE;
295 }
296
297
298 SM_STATE(SUPP_PAE, HELD)
299 {
300         SM_ENTRY(SUPP_PAE, HELD);
301         sm->heldWhile = sm->heldPeriod;
302         eapol_enable_timer_tick(sm);
303         eapol_sm_set_port_unauthorized(sm);
304         sm->cb_status = EAPOL_CB_FAILURE;
305 }
306
307
308 SM_STATE(SUPP_PAE, AUTHENTICATED)
309 {
310         SM_ENTRY(SUPP_PAE, AUTHENTICATED);
311         eapol_sm_set_port_authorized(sm);
312         sm->cb_status = EAPOL_CB_SUCCESS;
313 }
314
315
316 SM_STATE(SUPP_PAE, RESTART)
317 {
318         SM_ENTRY(SUPP_PAE, RESTART);
319         sm->eapRestart = TRUE;
320         if (sm->altAccept) {
321                 /*
322                  * Prevent EAP peer state machine from failing due to prior
323                  * external EAP success notification (altSuccess=TRUE in the
324                  * IDLE state could result in a transition to the FAILURE state.
325                  */
326                 wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
327                 sm->eapSuccess = FALSE;
328                 sm->altAccept = FALSE;
329         }
330 }
331
332
333 SM_STATE(SUPP_PAE, S_FORCE_AUTH)
334 {
335         SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
336         eapol_sm_set_port_authorized(sm);
337         sm->sPortMode = ForceAuthorized;
338 }
339
340
341 SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
342 {
343         SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
344         eapol_sm_set_port_unauthorized(sm);
345         sm->sPortMode = ForceUnauthorized;
346         eapol_sm_txLogoff(sm);
347 }
348
349
350 SM_STEP(SUPP_PAE)
351 {
352         if ((sm->userLogoff && !sm->logoffSent) &&
353             !(sm->initialize || !sm->portEnabled))
354                 SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
355         else if (((sm->portControl == Auto) &&
356                   (sm->sPortMode != sm->portControl)) ||
357                  sm->initialize || !sm->portEnabled)
358                 SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
359         else if ((sm->portControl == ForceAuthorized) &&
360                  (sm->sPortMode != sm->portControl) &&
361                  !(sm->initialize || !sm->portEnabled))
362                 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
363         else if ((sm->portControl == ForceUnauthorized) &&
364                  (sm->sPortMode != sm->portControl) &&
365                  !(sm->initialize || !sm->portEnabled))
366                 SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
367         else switch (sm->SUPP_PAE_state) {
368         case SUPP_PAE_UNKNOWN:
369                 break;
370         case SUPP_PAE_LOGOFF:
371                 if (!sm->userLogoff)
372                         SM_ENTER(SUPP_PAE, DISCONNECTED);
373                 break;
374         case SUPP_PAE_DISCONNECTED:
375                 SM_ENTER(SUPP_PAE, CONNECTING);
376                 break;
377         case SUPP_PAE_CONNECTING:
378                 if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
379                         SM_ENTER(SUPP_PAE, CONNECTING);
380                 else if (sm->startWhen == 0 &&
381                          sm->startCount >= sm->maxStart &&
382                          sm->portValid)
383                         SM_ENTER(SUPP_PAE, AUTHENTICATED);
384                 else if (sm->eapSuccess || sm->eapFail)
385                         SM_ENTER(SUPP_PAE, AUTHENTICATING);
386                 else if (sm->eapolEap)
387                         SM_ENTER(SUPP_PAE, RESTART);
388                 else if (sm->startWhen == 0 &&
389                          sm->startCount >= sm->maxStart &&
390                          !sm->portValid)
391                         SM_ENTER(SUPP_PAE, HELD);
392                 break;
393         case SUPP_PAE_AUTHENTICATING:
394                 if (sm->eapSuccess && !sm->portValid &&
395                     sm->conf.accept_802_1x_keys &&
396                     sm->conf.required_keys == 0) {
397                         wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
398                                    "plaintext connection; no EAPOL-Key frames "
399                                    "required");
400                         sm->portValid = TRUE;
401                         if (sm->ctx->eapol_done_cb)
402                                 sm->ctx->eapol_done_cb(sm->ctx->ctx);
403                 }
404                 if (sm->eapSuccess && sm->portValid)
405                         SM_ENTER(SUPP_PAE, AUTHENTICATED);
406                 else if (sm->eapFail || (sm->keyDone && !sm->portValid))
407                         SM_ENTER(SUPP_PAE, HELD);
408                 else if (sm->suppTimeout)
409                         SM_ENTER(SUPP_PAE, CONNECTING);
410                 else if (sm->eapTriggerStart)
411                         SM_ENTER(SUPP_PAE, CONNECTING);
412                 break;
413         case SUPP_PAE_HELD:
414                 if (sm->heldWhile == 0)
415                         SM_ENTER(SUPP_PAE, CONNECTING);
416                 else if (sm->eapolEap)
417                         SM_ENTER(SUPP_PAE, RESTART);
418                 break;
419         case SUPP_PAE_AUTHENTICATED:
420                 if (sm->eapolEap && sm->portValid)
421                         SM_ENTER(SUPP_PAE, RESTART);
422                 else if (!sm->portValid)
423                         SM_ENTER(SUPP_PAE, DISCONNECTED);
424                 break;
425         case SUPP_PAE_RESTART:
426                 if (!sm->eapRestart)
427                         SM_ENTER(SUPP_PAE, AUTHENTICATING);
428                 break;
429         case SUPP_PAE_S_FORCE_AUTH:
430                 break;
431         case SUPP_PAE_S_FORCE_UNAUTH:
432                 break;
433         }
434 }
435
436
437 SM_STATE(KEY_RX, NO_KEY_RECEIVE)
438 {
439         SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
440 }
441
442
443 SM_STATE(KEY_RX, KEY_RECEIVE)
444 {
445         SM_ENTRY(KEY_RX, KEY_RECEIVE);
446         eapol_sm_processKey(sm);
447         sm->rxKey = FALSE;
448 }
449
450
451 SM_STEP(KEY_RX)
452 {
453         if (sm->initialize || !sm->portEnabled)
454                 SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
455         switch (sm->KEY_RX_state) {
456         case KEY_RX_UNKNOWN:
457                 break;
458         case KEY_RX_NO_KEY_RECEIVE:
459                 if (sm->rxKey)
460                         SM_ENTER(KEY_RX, KEY_RECEIVE);
461                 break;
462         case KEY_RX_KEY_RECEIVE:
463                 if (sm->rxKey)
464                         SM_ENTER(KEY_RX, KEY_RECEIVE);
465                 break;
466         }
467 }
468
469
470 SM_STATE(SUPP_BE, REQUEST)
471 {
472         SM_ENTRY(SUPP_BE, REQUEST);
473         sm->authWhile = 0;
474         sm->eapReq = TRUE;
475         eapol_sm_getSuppRsp(sm);
476 }
477
478
479 SM_STATE(SUPP_BE, RESPONSE)
480 {
481         SM_ENTRY(SUPP_BE, RESPONSE);
482         eapol_sm_txSuppRsp(sm);
483         sm->eapResp = FALSE;
484 }
485
486
487 SM_STATE(SUPP_BE, SUCCESS)
488 {
489         SM_ENTRY(SUPP_BE, SUCCESS);
490         sm->keyRun = TRUE;
491         sm->suppSuccess = TRUE;
492
493 #ifdef CONFIG_EAP_PROXY
494         if (sm->use_eap_proxy) {
495                 if (eap_proxy_key_available(sm->eap_proxy)) {
496                         u8 *session_id, *emsk;
497                         size_t session_id_len, emsk_len;
498
499                         /* New key received - clear IEEE 802.1X EAPOL-Key replay
500                          * counter */
501                         sm->replay_counter_valid = FALSE;
502
503                         session_id = eap_proxy_get_eap_session_id(
504                                 sm->eap_proxy, &session_id_len);
505                         emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
506                         if (sm->config->erp && session_id && emsk) {
507                                 eap_peer_erp_init(sm->eap, session_id,
508                                                   session_id_len, emsk,
509                                                   emsk_len);
510                         } else {
511                                 os_free(session_id);
512                                 bin_clear_free(emsk, emsk_len);
513                         }
514                 }
515                 return;
516         }
517 #endif /* CONFIG_EAP_PROXY */
518
519         if (eap_key_available(sm->eap)) {
520                 /* New key received - clear IEEE 802.1X EAPOL-Key replay
521                  * counter */
522                 sm->replay_counter_valid = FALSE;
523         }
524 }
525
526
527 SM_STATE(SUPP_BE, FAIL)
528 {
529         SM_ENTRY(SUPP_BE, FAIL);
530         sm->suppFail = TRUE;
531 }
532
533
534 SM_STATE(SUPP_BE, TIMEOUT)
535 {
536         SM_ENTRY(SUPP_BE, TIMEOUT);
537         sm->suppTimeout = TRUE;
538 }
539
540
541 SM_STATE(SUPP_BE, IDLE)
542 {
543         SM_ENTRY(SUPP_BE, IDLE);
544         sm->suppStart = FALSE;
545         sm->initial_req = TRUE;
546 }
547
548
549 SM_STATE(SUPP_BE, INITIALIZE)
550 {
551         SM_ENTRY(SUPP_BE, INITIALIZE);
552         eapol_sm_abortSupp(sm);
553         sm->suppAbort = FALSE;
554
555         /*
556          * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so
557          * allows the timer tick to be stopped more quickly when the port is
558          * not enabled. Since this variable is used only within RECEIVE state,
559          * clearing it on initialization does not change actual state machine
560          * behavior.
561          */
562         sm->authWhile = 0;
563 }
564
565
566 SM_STATE(SUPP_BE, RECEIVE)
567 {
568         SM_ENTRY(SUPP_BE, RECEIVE);
569         sm->authWhile = sm->authPeriod;
570         eapol_enable_timer_tick(sm);
571         sm->eapolEap = FALSE;
572         sm->eapNoResp = FALSE;
573         sm->initial_req = FALSE;
574 }
575
576
577 SM_STEP(SUPP_BE)
578 {
579         if (sm->initialize || sm->suppAbort)
580                 SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
581         else switch (sm->SUPP_BE_state) {
582         case SUPP_BE_UNKNOWN:
583                 break;
584         case SUPP_BE_REQUEST:
585                 /*
586                  * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
587                  * and SUCCESS based on eapFail and eapSuccess, respectively.
588                  * However, IEEE Std 802.1X-2004 is also specifying that
589                  * eapNoResp should be set in conjunction with eapSuccess and
590                  * eapFail which would mean that more than one of the
591                  * transitions here would be activated at the same time.
592                  * Skipping RESPONSE and/or RECEIVE states in these cases can
593                  * cause problems and the direct transitions to do not seem
594                  * correct. Because of this, the conditions for these
595                  * transitions are verified only after eapNoResp. They are
596                  * unlikely to be used since eapNoResp should always be set if
597                  * either of eapSuccess or eapFail is set.
598                  */
599                 if (sm->eapResp && sm->eapNoResp) {
600                         wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
601                                    "eapResp and eapNoResp set?!");
602                 }
603                 if (sm->eapResp)
604                         SM_ENTER(SUPP_BE, RESPONSE);
605                 else if (sm->eapNoResp)
606                         SM_ENTER(SUPP_BE, RECEIVE);
607                 else if (sm->eapFail)
608                         SM_ENTER(SUPP_BE, FAIL);
609                 else if (sm->eapSuccess)
610                         SM_ENTER(SUPP_BE, SUCCESS);
611                 break;
612         case SUPP_BE_RESPONSE:
613                 SM_ENTER(SUPP_BE, RECEIVE);
614                 break;
615         case SUPP_BE_SUCCESS:
616                 SM_ENTER(SUPP_BE, IDLE);
617                 break;
618         case SUPP_BE_FAIL:
619                 SM_ENTER(SUPP_BE, IDLE);
620                 break;
621         case SUPP_BE_TIMEOUT:
622                 SM_ENTER(SUPP_BE, IDLE);
623                 break;
624         case SUPP_BE_IDLE:
625                 if (sm->eapFail && sm->suppStart)
626                         SM_ENTER(SUPP_BE, FAIL);
627                 else if (sm->eapolEap && sm->suppStart)
628                         SM_ENTER(SUPP_BE, REQUEST);
629                 else if (sm->eapSuccess && sm->suppStart)
630                         SM_ENTER(SUPP_BE, SUCCESS);
631                 break;
632         case SUPP_BE_INITIALIZE:
633                 SM_ENTER(SUPP_BE, IDLE);
634                 break;
635         case SUPP_BE_RECEIVE:
636                 if (sm->eapolEap)
637                         SM_ENTER(SUPP_BE, REQUEST);
638                 else if (sm->eapFail)
639                         SM_ENTER(SUPP_BE, FAIL);
640                 else if (sm->authWhile == 0)
641                         SM_ENTER(SUPP_BE, TIMEOUT);
642                 else if (sm->eapSuccess)
643                         SM_ENTER(SUPP_BE, SUCCESS);
644                 break;
645         }
646 }
647
648
649 static void eapol_sm_txLogoff(struct eapol_sm *sm)
650 {
651         wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
652         sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
653                             IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
654         sm->dot1xSuppEapolLogoffFramesTx++;
655         sm->dot1xSuppEapolFramesTx++;
656 }
657
658
659 static void eapol_sm_txStart(struct eapol_sm *sm)
660 {
661         wpa_printf(MSG_DEBUG, "EAPOL: txStart");
662         sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
663                             IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
664         sm->dot1xSuppEapolStartFramesTx++;
665         sm->dot1xSuppEapolFramesTx++;
666 }
667
668
669 #define IEEE8021X_ENCR_KEY_LEN 32
670 #define IEEE8021X_SIGN_KEY_LEN 32
671
672 struct eap_key_data {
673         u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
674         u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
675 };
676
677
678 static void eapol_sm_processKey(struct eapol_sm *sm)
679 {
680 #ifndef CONFIG_FIPS
681         struct ieee802_1x_hdr *hdr;
682         struct ieee802_1x_eapol_key *key;
683         struct eap_key_data keydata;
684         u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
685 #ifndef CONFIG_NO_RC4
686         u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
687 #endif /* CONFIG_NO_RC4 */
688         int key_len, res, sign_key_len, encr_key_len;
689         u16 rx_key_length;
690         size_t plen;
691
692         wpa_printf(MSG_DEBUG, "EAPOL: processKey");
693         if (sm->last_rx_key == NULL)
694                 return;
695
696         if (!sm->conf.accept_802_1x_keys) {
697                 wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
698                            " even though this was not accepted - "
699                            "ignoring this packet");
700                 return;
701         }
702
703         if (sm->last_rx_key_len < sizeof(*hdr) + sizeof(*key))
704                 return;
705         hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
706         key = (struct ieee802_1x_eapol_key *) (hdr + 1);
707         plen = be_to_host16(hdr->length);
708         if (sizeof(*hdr) + plen > sm->last_rx_key_len || plen < sizeof(*key)) {
709                 wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
710                 return;
711         }
712         rx_key_length = WPA_GET_BE16(key->key_length);
713         wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
714                    "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
715                    hdr->version, hdr->type, be_to_host16(hdr->length),
716                    key->type, rx_key_length, key->key_index);
717
718         eapol_sm_notify_lower_layer_success(sm, 1);
719         sign_key_len = IEEE8021X_SIGN_KEY_LEN;
720         encr_key_len = IEEE8021X_ENCR_KEY_LEN;
721         res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
722         if (res < 0) {
723                 wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
724                            "decrypting EAPOL-Key keys");
725                 return;
726         }
727         if (res == 16) {
728                 /* LEAP derives only 16 bytes of keying material. */
729                 res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
730                 if (res) {
731                         wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
732                                    "master key for decrypting EAPOL-Key keys");
733                         return;
734                 }
735                 sign_key_len = 16;
736                 encr_key_len = 16;
737                 os_memcpy(keydata.sign_key, keydata.encr_key, 16);
738         } else if (res) {
739                 wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
740                            "data for decrypting EAPOL-Key keys (res=%d)", res);
741                 return;
742         }
743
744         /* The key replay_counter must increase when same master key */
745         if (sm->replay_counter_valid &&
746             os_memcmp(sm->last_replay_counter, key->replay_counter,
747                       IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
748                 wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
749                            "not increase - ignoring key");
750                 wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
751                             sm->last_replay_counter,
752                             IEEE8021X_REPLAY_COUNTER_LEN);
753                 wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
754                             key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
755                 return;
756         }
757
758         /* Verify key signature (HMAC-MD5) */
759         os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
760         os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
761         hmac_md5(keydata.sign_key, sign_key_len,
762                  sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
763                  key->key_signature);
764         if (os_memcmp_const(orig_key_sign, key->key_signature,
765                             IEEE8021X_KEY_SIGN_LEN) != 0) {
766                 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
767                            "EAPOL-Key packet");
768                 os_memcpy(key->key_signature, orig_key_sign,
769                           IEEE8021X_KEY_SIGN_LEN);
770                 return;
771         }
772         wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
773
774         key_len = plen - sizeof(*key);
775         if (key_len > 32 || rx_key_length > 32) {
776                 wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
777                            key_len ? key_len : rx_key_length);
778                 return;
779         }
780         if (key_len == rx_key_length) {
781 #ifdef CONFIG_NO_RC4
782                 if (encr_key_len) {
783                         /* otherwise unused */
784                 }
785                 wpa_printf(MSG_ERROR, "EAPOL: RC4 not supported in the build");
786                 return;
787 #else /* CONFIG_NO_RC4 */
788                 os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
789                 os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
790                           encr_key_len);
791                 os_memcpy(datakey, key + 1, key_len);
792                 rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
793                          datakey, key_len);
794                 wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
795                                 datakey, key_len);
796 #endif /* CONFIG_NO_RC4 */
797         } else if (key_len == 0) {
798                 /*
799                  * IEEE 802.1X-2004 specifies that least significant Key Length
800                  * octets from MS-MPPE-Send-Key are used as the key if the key
801                  * data is not present. This seems to be meaning the beginning
802                  * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
803                  * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
804                  * Anyway, taking the beginning of the keying material from EAP
805                  * seems to interoperate with Authenticators.
806                  */
807                 key_len = rx_key_length;
808                 os_memcpy(datakey, keydata.encr_key, key_len);
809                 wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
810                                 "material data encryption key",
811                                 datakey, key_len);
812         } else {
813                 wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
814                            "(key_length=%d)", key_len, rx_key_length);
815                 return;
816         }
817
818         sm->replay_counter_valid = TRUE;
819         os_memcpy(sm->last_replay_counter, key->replay_counter,
820                   IEEE8021X_REPLAY_COUNTER_LEN);
821
822         wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
823                    "len %d",
824                    key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
825                    "unicast" : "broadcast",
826                    key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
827
828         if (sm->ctx->set_wep_key &&
829             sm->ctx->set_wep_key(sm->ctx->ctx,
830                                  key->key_index & IEEE8021X_KEY_INDEX_FLAG,
831                                  key->key_index & IEEE8021X_KEY_INDEX_MASK,
832                                  datakey, key_len) < 0) {
833                 wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
834                            " driver.");
835         } else {
836                 if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
837                         sm->unicast_key_received = TRUE;
838                 else
839                         sm->broadcast_key_received = TRUE;
840
841                 if ((sm->unicast_key_received ||
842                      !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
843                     (sm->broadcast_key_received ||
844                      !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
845                 {
846                         wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
847                                    "frames received");
848                         sm->portValid = TRUE;
849                         if (sm->ctx->eapol_done_cb)
850                                 sm->ctx->eapol_done_cb(sm->ctx->ctx);
851                 }
852         }
853 #endif /* CONFIG_FIPS */
854 }
855
856
857 static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
858 {
859         wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
860         /* EAP layer processing; no special code is needed, since Supplicant
861          * Backend state machine is waiting for eapNoResp or eapResp to be set
862          * and these are only set in the EAP state machine when the processing
863          * has finished. */
864 }
865
866
867 static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
868 {
869         struct wpabuf *resp;
870
871         wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
872
873 #ifdef CONFIG_EAP_PROXY
874         if (sm->use_eap_proxy) {
875                 /* Get EAP Response from EAP Proxy */
876                 resp = eap_proxy_get_eapRespData(sm->eap_proxy);
877                 if (resp == NULL) {
878                         wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
879                                    "response data not available");
880                         return;
881                 }
882         } else
883 #endif /* CONFIG_EAP_PROXY */
884
885         resp = eap_get_eapRespData(sm->eap);
886         if (resp == NULL) {
887                 wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
888                            "not available");
889                 return;
890         }
891
892         /* Send EAP-Packet from the EAP layer to the Authenticator */
893         sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
894                             IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
895                             wpabuf_len(resp));
896
897         /* eapRespData is not used anymore, so free it here */
898         wpabuf_free(resp);
899
900         if (sm->initial_req)
901                 sm->dot1xSuppEapolReqIdFramesRx++;
902         else
903                 sm->dot1xSuppEapolReqFramesRx++;
904         sm->dot1xSuppEapolRespFramesTx++;
905         sm->dot1xSuppEapolFramesTx++;
906 }
907
908
909 static void eapol_sm_abortSupp(struct eapol_sm *sm)
910 {
911         /* release system resources that may have been allocated for the
912          * authentication session */
913         os_free(sm->last_rx_key);
914         sm->last_rx_key = NULL;
915         wpabuf_free(sm->eapReqData);
916         sm->eapReqData = NULL;
917         eap_sm_abort(sm->eap);
918 #ifdef CONFIG_EAP_PROXY
919         eap_proxy_sm_abort(sm->eap_proxy);
920 #endif /* CONFIG_EAP_PROXY */
921 }
922
923
924 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
925 {
926         eapol_sm_step(timeout_ctx);
927 }
928
929
930 static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
931 {
932         int cb;
933
934         cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
935         sm->force_authorized_update = FALSE;
936         sm->suppPortStatus = Authorized;
937         if (cb && sm->ctx->port_cb)
938                 sm->ctx->port_cb(sm->ctx->ctx, 1);
939 }
940
941
942 static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
943 {
944         int cb;
945
946         cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
947         sm->force_authorized_update = FALSE;
948         sm->suppPortStatus = Unauthorized;
949         if (cb && sm->ctx->port_cb)
950                 sm->ctx->port_cb(sm->ctx->ctx, 0);
951 }
952
953
954 /**
955  * eapol_sm_step - EAPOL state machine step function
956  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
957  *
958  * This function is called to notify the state machine about changed external
959  * variables. It will step through the EAPOL state machines in loop to process
960  * all triggered state changes.
961  */
962 void eapol_sm_step(struct eapol_sm *sm)
963 {
964         int i;
965
966         /* In theory, it should be ok to run this in loop until !changed.
967          * However, it is better to use a limit on number of iterations to
968          * allow events (e.g., SIGTERM) to stop the program cleanly if the
969          * state machine were to generate a busy loop. */
970         for (i = 0; i < 100; i++) {
971                 sm->changed = FALSE;
972                 SM_STEP_RUN(SUPP_PAE);
973                 SM_STEP_RUN(KEY_RX);
974                 SM_STEP_RUN(SUPP_BE);
975 #ifdef CONFIG_EAP_PROXY
976                 if (sm->use_eap_proxy) {
977                         /* Drive the EAP proxy state machine */
978                         if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
979                                 sm->changed = TRUE;
980                 } else
981 #endif /* CONFIG_EAP_PROXY */
982                 if (eap_peer_sm_step(sm->eap))
983                         sm->changed = TRUE;
984                 if (!sm->changed)
985                         break;
986         }
987
988         if (sm->changed) {
989                 /* restart EAPOL state machine step from timeout call in order
990                  * to allow other events to be processed. */
991                 eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
992                 eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
993         }
994
995         if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
996                 enum eapol_supp_result result;
997                 if (sm->cb_status == EAPOL_CB_SUCCESS)
998                         result = EAPOL_SUPP_RESULT_SUCCESS;
999                 else if (eap_peer_was_failure_expected(sm->eap))
1000                         result = EAPOL_SUPP_RESULT_EXPECTED_FAILURE;
1001                 else
1002                         result = EAPOL_SUPP_RESULT_FAILURE;
1003                 sm->cb_status = EAPOL_CB_IN_PROGRESS;
1004                 sm->ctx->cb(sm, result, sm->ctx->cb_ctx);
1005         }
1006 }
1007
1008
1009 #ifdef CONFIG_CTRL_IFACE
1010 static const char *eapol_supp_pae_state(int state)
1011 {
1012         switch (state) {
1013         case SUPP_PAE_LOGOFF:
1014                 return "LOGOFF";
1015         case SUPP_PAE_DISCONNECTED:
1016                 return "DISCONNECTED";
1017         case SUPP_PAE_CONNECTING:
1018                 return "CONNECTING";
1019         case SUPP_PAE_AUTHENTICATING:
1020                 return "AUTHENTICATING";
1021         case SUPP_PAE_HELD:
1022                 return "HELD";
1023         case SUPP_PAE_AUTHENTICATED:
1024                 return "AUTHENTICATED";
1025         case SUPP_PAE_RESTART:
1026                 return "RESTART";
1027         default:
1028                 return "UNKNOWN";
1029         }
1030 }
1031
1032
1033 static const char *eapol_supp_be_state(int state)
1034 {
1035         switch (state) {
1036         case SUPP_BE_REQUEST:
1037                 return "REQUEST";
1038         case SUPP_BE_RESPONSE:
1039                 return "RESPONSE";
1040         case SUPP_BE_SUCCESS:
1041                 return "SUCCESS";
1042         case SUPP_BE_FAIL:
1043                 return "FAIL";
1044         case SUPP_BE_TIMEOUT:
1045                 return "TIMEOUT";
1046         case SUPP_BE_IDLE:
1047                 return "IDLE";
1048         case SUPP_BE_INITIALIZE:
1049                 return "INITIALIZE";
1050         case SUPP_BE_RECEIVE:
1051                 return "RECEIVE";
1052         default:
1053                 return "UNKNOWN";
1054         }
1055 }
1056
1057
1058 static const char * eapol_port_status(PortStatus status)
1059 {
1060         if (status == Authorized)
1061                 return "Authorized";
1062         else
1063                 return "Unauthorized";
1064 }
1065 #endif /* CONFIG_CTRL_IFACE */
1066
1067
1068 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1069 static const char * eapol_port_control(PortControl ctrl)
1070 {
1071         switch (ctrl) {
1072         case Auto:
1073                 return "Auto";
1074         case ForceUnauthorized:
1075                 return "ForceUnauthorized";
1076         case ForceAuthorized:
1077                 return "ForceAuthorized";
1078         default:
1079                 return "Unknown";
1080         }
1081 }
1082 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1083
1084
1085 /**
1086  * eapol_sm_configure - Set EAPOL variables
1087  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1088  * @heldPeriod: dot1xSuppHeldPeriod
1089  * @authPeriod: dot1xSuppAuthPeriod
1090  * @startPeriod: dot1xSuppStartPeriod
1091  * @maxStart: dot1xSuppMaxStart
1092  *
1093  * Set configurable EAPOL state machine variables. Each variable can be set to
1094  * the given value or ignored if set to -1 (to set only some of the variables).
1095  */
1096 void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
1097                         int startPeriod, int maxStart)
1098 {
1099         if (sm == NULL)
1100                 return;
1101         if (heldPeriod >= 0)
1102                 sm->heldPeriod = heldPeriod;
1103         if (authPeriod >= 0)
1104                 sm->authPeriod = authPeriod;
1105         if (startPeriod >= 0)
1106                 sm->startPeriod = startPeriod;
1107         if (maxStart >= 0)
1108                 sm->maxStart = maxStart;
1109 }
1110
1111
1112 /**
1113  * eapol_sm_get_method_name - Get EAPOL method name
1114  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1115  * Returns: Static string containing name of current eap method or NULL
1116  */
1117 const char * eapol_sm_get_method_name(struct eapol_sm *sm)
1118 {
1119         if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
1120             sm->suppPortStatus != Authorized)
1121                 return NULL;
1122
1123         return eap_sm_get_method_name(sm->eap);
1124 }
1125
1126
1127 #ifdef CONFIG_CTRL_IFACE
1128 /**
1129  * eapol_sm_get_status - Get EAPOL state machine status
1130  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1131  * @buf: Buffer for status information
1132  * @buflen: Maximum buffer length
1133  * @verbose: Whether to include verbose status information
1134  * Returns: Number of bytes written to buf.
1135  *
1136  * Query EAPOL state machine for status information. This function fills in a
1137  * text area with current status information from the EAPOL state machine. If
1138  * the buffer (buf) is not large enough, status information will be truncated
1139  * to fit the buffer.
1140  */
1141 int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
1142                         int verbose)
1143 {
1144         int len, ret;
1145         if (sm == NULL)
1146                 return 0;
1147
1148         len = os_snprintf(buf, buflen,
1149                           "Supplicant PAE state=%s\n"
1150                           "suppPortStatus=%s\n",
1151                           eapol_supp_pae_state(sm->SUPP_PAE_state),
1152                           eapol_port_status(sm->suppPortStatus));
1153         if (os_snprintf_error(buflen, len))
1154                 return 0;
1155
1156         if (verbose) {
1157                 ret = os_snprintf(buf + len, buflen - len,
1158                                   "heldPeriod=%u\n"
1159                                   "authPeriod=%u\n"
1160                                   "startPeriod=%u\n"
1161                                   "maxStart=%u\n"
1162                                   "portControl=%s\n"
1163                                   "Supplicant Backend state=%s\n",
1164                                   sm->heldPeriod,
1165                                   sm->authPeriod,
1166                                   sm->startPeriod,
1167                                   sm->maxStart,
1168                                   eapol_port_control(sm->portControl),
1169                                   eapol_supp_be_state(sm->SUPP_BE_state));
1170                 if (os_snprintf_error(buflen - len, ret))
1171                         return len;
1172                 len += ret;
1173         }
1174
1175 #ifdef CONFIG_EAP_PROXY
1176         if (sm->use_eap_proxy)
1177                 len += eap_proxy_sm_get_status(sm->eap_proxy,
1178                                                buf + len, buflen - len,
1179                                                verbose);
1180         else
1181 #endif /* CONFIG_EAP_PROXY */
1182         len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
1183
1184         return len;
1185 }
1186
1187
1188 /**
1189  * eapol_sm_get_mib - Get EAPOL state machine MIBs
1190  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1191  * @buf: Buffer for MIB information
1192  * @buflen: Maximum buffer length
1193  * Returns: Number of bytes written to buf.
1194  *
1195  * Query EAPOL state machine for MIB information. This function fills in a
1196  * text area with current MIB information from the EAPOL state machine. If
1197  * the buffer (buf) is not large enough, MIB information will be truncated to
1198  * fit the buffer.
1199  */
1200 int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
1201 {
1202         size_t len;
1203         int ret;
1204
1205         if (sm == NULL)
1206                 return 0;
1207         ret = os_snprintf(buf, buflen,
1208                           "dot1xSuppPaeState=%d\n"
1209                           "dot1xSuppHeldPeriod=%u\n"
1210                           "dot1xSuppAuthPeriod=%u\n"
1211                           "dot1xSuppStartPeriod=%u\n"
1212                           "dot1xSuppMaxStart=%u\n"
1213                           "dot1xSuppSuppControlledPortStatus=%s\n"
1214                           "dot1xSuppBackendPaeState=%d\n",
1215                           sm->SUPP_PAE_state,
1216                           sm->heldPeriod,
1217                           sm->authPeriod,
1218                           sm->startPeriod,
1219                           sm->maxStart,
1220                           sm->suppPortStatus == Authorized ?
1221                           "Authorized" : "Unauthorized",
1222                           sm->SUPP_BE_state);
1223
1224         if (os_snprintf_error(buflen, ret))
1225                 return 0;
1226         len = ret;
1227
1228         ret = os_snprintf(buf + len, buflen - len,
1229                           "dot1xSuppEapolFramesRx=%u\n"
1230                           "dot1xSuppEapolFramesTx=%u\n"
1231                           "dot1xSuppEapolStartFramesTx=%u\n"
1232                           "dot1xSuppEapolLogoffFramesTx=%u\n"
1233                           "dot1xSuppEapolRespFramesTx=%u\n"
1234                           "dot1xSuppEapolReqIdFramesRx=%u\n"
1235                           "dot1xSuppEapolReqFramesRx=%u\n"
1236                           "dot1xSuppInvalidEapolFramesRx=%u\n"
1237                           "dot1xSuppEapLengthErrorFramesRx=%u\n"
1238                           "dot1xSuppLastEapolFrameVersion=%u\n"
1239                           "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
1240                           sm->dot1xSuppEapolFramesRx,
1241                           sm->dot1xSuppEapolFramesTx,
1242                           sm->dot1xSuppEapolStartFramesTx,
1243                           sm->dot1xSuppEapolLogoffFramesTx,
1244                           sm->dot1xSuppEapolRespFramesTx,
1245                           sm->dot1xSuppEapolReqIdFramesRx,
1246                           sm->dot1xSuppEapolReqFramesRx,
1247                           sm->dot1xSuppInvalidEapolFramesRx,
1248                           sm->dot1xSuppEapLengthErrorFramesRx,
1249                           sm->dot1xSuppLastEapolFrameVersion,
1250                           MAC2STR(sm->dot1xSuppLastEapolFrameSource));
1251
1252         if (os_snprintf_error(buflen - len, ret))
1253                 return len;
1254         len += ret;
1255
1256         return len;
1257 }
1258 #endif /* CONFIG_CTRL_IFACE */
1259
1260
1261 /**
1262  * eapol_sm_rx_eapol - Process received EAPOL frames
1263  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1264  * @src: Source MAC address of the EAPOL packet
1265  * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
1266  * @len: Length of the EAPOL frame
1267  * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
1268  * -1 failure
1269  */
1270 int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
1271                       size_t len)
1272 {
1273         const struct ieee802_1x_hdr *hdr;
1274         const struct ieee802_1x_eapol_key *key;
1275         int data_len;
1276         int res = 1;
1277         size_t plen;
1278
1279         if (sm == NULL)
1280                 return 0;
1281         sm->dot1xSuppEapolFramesRx++;
1282         if (len < sizeof(*hdr)) {
1283                 sm->dot1xSuppInvalidEapolFramesRx++;
1284                 return 0;
1285         }
1286         hdr = (const struct ieee802_1x_hdr *) buf;
1287         sm->dot1xSuppLastEapolFrameVersion = hdr->version;
1288         os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
1289         if (hdr->version < EAPOL_VERSION) {
1290                 /* TODO: backwards compatibility */
1291         }
1292         plen = be_to_host16(hdr->length);
1293         if (plen > len - sizeof(*hdr)) {
1294                 sm->dot1xSuppEapLengthErrorFramesRx++;
1295                 return 0;
1296         }
1297 #ifdef CONFIG_WPS
1298         if (sm->conf.wps && sm->conf.workaround &&
1299             plen < len - sizeof(*hdr) &&
1300             hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
1301             len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
1302                 const struct eap_hdr *ehdr =
1303                         (const struct eap_hdr *) (hdr + 1);
1304                 u16 elen;
1305
1306                 elen = be_to_host16(ehdr->length);
1307                 if (elen > plen && elen <= len - sizeof(*hdr)) {
1308                         /*
1309                          * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
1310                          * packets with too short EAPOL header length field
1311                          * (14 octets). This is fixed in firmware Ver.1.49.
1312                          * As a workaround, fix the EAPOL header based on the
1313                          * correct length in the EAP packet.
1314                          */
1315                         wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
1316                                    "payload length based on EAP header: "
1317                                    "%d -> %d", (int) plen, elen);
1318                         plen = elen;
1319                 }
1320         }
1321 #endif /* CONFIG_WPS */
1322         data_len = plen + sizeof(*hdr);
1323
1324         switch (hdr->type) {
1325         case IEEE802_1X_TYPE_EAP_PACKET:
1326                 if (sm->conf.workaround) {
1327                         /*
1328                          * An AP has been reported to send out EAP message with
1329                          * undocumented code 10 at some point near the
1330                          * completion of EAP authentication. This can result in
1331                          * issues with the unexpected EAP message triggering
1332                          * restart of EAPOL authentication. Avoid this by
1333                          * skipping the message without advancing the state
1334                          * machine.
1335                          */
1336                         const struct eap_hdr *ehdr =
1337                                 (const struct eap_hdr *) (hdr + 1);
1338                         if (plen >= sizeof(*ehdr) && ehdr->code == 10) {
1339                                 wpa_printf(MSG_DEBUG, "EAPOL: Ignore EAP packet with unknown code 10");
1340                                 break;
1341                         }
1342                 }
1343
1344                 if (sm->cached_pmk) {
1345                         /* Trying to use PMKSA caching, but Authenticator did
1346                          * not seem to have a matching entry. Need to restart
1347                          * EAPOL state machines.
1348                          */
1349                         eapol_sm_abort_cached(sm);
1350                 }
1351                 wpabuf_free(sm->eapReqData);
1352                 sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
1353                 if (sm->eapReqData) {
1354                         wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
1355                                    "frame");
1356                         sm->eapolEap = TRUE;
1357 #ifdef CONFIG_EAP_PROXY
1358                         if (sm->use_eap_proxy) {
1359                                 eap_proxy_packet_update(
1360                                         sm->eap_proxy,
1361                                         wpabuf_mhead_u8(sm->eapReqData),
1362                                         wpabuf_len(sm->eapReqData));
1363                                 wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
1364                                            "EAP Req updated");
1365                         }
1366 #endif /* CONFIG_EAP_PROXY */
1367                         eapol_sm_step(sm);
1368                 }
1369                 break;
1370         case IEEE802_1X_TYPE_EAPOL_KEY:
1371                 if (plen < sizeof(*key)) {
1372                         wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
1373                                    "frame received");
1374                         break;
1375                 }
1376                 key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
1377                 if (key->type == EAPOL_KEY_TYPE_WPA ||
1378                     key->type == EAPOL_KEY_TYPE_RSN) {
1379                         /* WPA Supplicant takes care of this frame. */
1380                         wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
1381                                    "frame in EAPOL state machines");
1382                         res = 0;
1383                         break;
1384                 }
1385                 if (key->type != EAPOL_KEY_TYPE_RC4) {
1386                         wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
1387                                    "EAPOL-Key type %d", key->type);
1388                         break;
1389                 }
1390                 os_free(sm->last_rx_key);
1391                 sm->last_rx_key = os_malloc(data_len);
1392                 if (sm->last_rx_key) {
1393                         wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
1394                                    "frame");
1395                         os_memcpy(sm->last_rx_key, buf, data_len);
1396                         sm->last_rx_key_len = data_len;
1397                         sm->rxKey = TRUE;
1398                         eapol_sm_step(sm);
1399                 }
1400                 break;
1401 #ifdef CONFIG_MACSEC
1402         case IEEE802_1X_TYPE_EAPOL_MKA:
1403                 wpa_printf(MSG_EXCESSIVE,
1404                            "EAPOL type %d will be handled by MKA",
1405                            hdr->type);
1406                 break;
1407 #endif /* CONFIG_MACSEC */
1408         default:
1409                 wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
1410                            hdr->type);
1411                 sm->dot1xSuppInvalidEapolFramesRx++;
1412                 break;
1413         }
1414
1415         return res;
1416 }
1417
1418
1419 /**
1420  * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
1421  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1422  *
1423  * Notify EAPOL state machine about transmitted EAPOL packet from an external
1424  * component, e.g., WPA. This will update the statistics.
1425  */
1426 void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
1427 {
1428         if (sm)
1429                 sm->dot1xSuppEapolFramesTx++;
1430 }
1431
1432
1433 /**
1434  * eapol_sm_notify_portEnabled - Notification about portEnabled change
1435  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1436  * @enabled: New portEnabled value
1437  *
1438  * Notify EAPOL state machine about new portEnabled value.
1439  */
1440 void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
1441 {
1442         if (sm == NULL)
1443                 return;
1444         wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1445                    "portEnabled=%d", enabled);
1446         if (sm->portEnabled != enabled)
1447                 sm->force_authorized_update = TRUE;
1448         sm->portEnabled = enabled;
1449         eapol_sm_step(sm);
1450 }
1451
1452
1453 /**
1454  * eapol_sm_notify_portValid - Notification about portValid change
1455  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1456  * @valid: New portValid value
1457  *
1458  * Notify EAPOL state machine about new portValid value.
1459  */
1460 void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
1461 {
1462         if (sm == NULL)
1463                 return;
1464         wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1465                    "portValid=%d", valid);
1466         sm->portValid = valid;
1467         eapol_sm_step(sm);
1468 }
1469
1470
1471 /**
1472  * eapol_sm_notify_eap_success - Notification of external EAP success trigger
1473  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1474  * @success: %TRUE = set success, %FALSE = clear success
1475  *
1476  * Notify the EAPOL state machine that external event has forced EAP state to
1477  * success (success = %TRUE). This can be cleared by setting success = %FALSE.
1478  *
1479  * This function is called to update EAP state when WPA-PSK key handshake has
1480  * been completed successfully since WPA-PSK does not use EAP state machine.
1481  */
1482 void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
1483 {
1484         if (sm == NULL)
1485                 return;
1486         wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1487                    "EAP success=%d", success);
1488         sm->eapSuccess = success;
1489         sm->altAccept = success;
1490         if (success)
1491                 eap_notify_success(sm->eap);
1492         eapol_sm_step(sm);
1493 }
1494
1495
1496 /**
1497  * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
1498  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1499  * @fail: %TRUE = set failure, %FALSE = clear failure
1500  *
1501  * Notify EAPOL state machine that external event has forced EAP state to
1502  * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1503  */
1504 void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
1505 {
1506         if (sm == NULL)
1507                 return;
1508         wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1509                    "EAP fail=%d", fail);
1510         sm->eapFail = fail;
1511         sm->altReject = fail;
1512         eapol_sm_step(sm);
1513 }
1514
1515
1516 /**
1517  * eapol_sm_notify_config - Notification of EAPOL configuration change
1518  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1519  * @config: Pointer to current network EAP configuration
1520  * @conf: Pointer to EAPOL configuration data
1521  *
1522  * Notify EAPOL state machine that configuration has changed. config will be
1523  * stored as a backpointer to network configuration. This can be %NULL to clear
1524  * the stored pointed. conf will be copied to local EAPOL/EAP configuration
1525  * data. If conf is %NULL, this part of the configuration change will be
1526  * skipped.
1527  */
1528 void eapol_sm_notify_config(struct eapol_sm *sm,
1529                             struct eap_peer_config *config,
1530                             const struct eapol_config *conf)
1531 {
1532         if (sm == NULL)
1533                 return;
1534
1535         sm->config = config;
1536 #ifdef CONFIG_EAP_PROXY
1537         sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
1538 #endif /* CONFIG_EAP_PROXY */
1539
1540         if (conf == NULL)
1541                 return;
1542
1543         sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
1544         sm->conf.required_keys = conf->required_keys;
1545         sm->conf.fast_reauth = conf->fast_reauth;
1546         sm->conf.workaround = conf->workaround;
1547         sm->conf.wps = conf->wps;
1548 #ifdef CONFIG_EAP_PROXY
1549         if (sm->use_eap_proxy) {
1550                 /* Using EAP Proxy, so skip EAP state machine update */
1551                 return;
1552         }
1553 #endif /* CONFIG_EAP_PROXY */
1554         if (sm->eap) {
1555                 eap_set_fast_reauth(sm->eap, conf->fast_reauth);
1556                 eap_set_workaround(sm->eap, conf->workaround);
1557                 eap_set_force_disabled(sm->eap, conf->eap_disabled);
1558                 eap_set_external_sim(sm->eap, conf->external_sim);
1559         }
1560 }
1561
1562
1563 /**
1564  * eapol_sm_get_key - Get master session key (MSK) from EAP
1565  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1566  * @key: Pointer for key buffer
1567  * @len: Number of bytes to copy to key
1568  * Returns: 0 on success (len of key available), maximum available key len
1569  * (>0) if key is available but it is shorter than len, or -1 on failure.
1570  *
1571  * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
1572  * is available only after a successful authentication.
1573  */
1574 int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
1575 {
1576         const u8 *eap_key;
1577         size_t eap_len;
1578
1579 #ifdef CONFIG_EAP_PROXY
1580         if (sm && sm->use_eap_proxy) {
1581                 /* Get key from EAP proxy */
1582                 if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
1583                         wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1584                         return -1;
1585                 }
1586                 eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
1587                 if (eap_key == NULL) {
1588                         wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
1589                                    "eapKeyData");
1590                         return -1;
1591                 }
1592                 goto key_fetched;
1593         }
1594 #endif /* CONFIG_EAP_PROXY */
1595         if (sm == NULL || !eap_key_available(sm->eap)) {
1596                 wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
1597                 return -1;
1598         }
1599         eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
1600         if (eap_key == NULL) {
1601                 wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
1602                 return -1;
1603         }
1604 #ifdef CONFIG_EAP_PROXY
1605 key_fetched:
1606 #endif /* CONFIG_EAP_PROXY */
1607         if (len > eap_len) {
1608                 wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
1609                            "available (len=%lu)",
1610                            (unsigned long) len, (unsigned long) eap_len);
1611                 return eap_len;
1612         }
1613         os_memcpy(key, eap_key, len);
1614         wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
1615                    (unsigned long) len);
1616         return 0;
1617 }
1618
1619
1620 /**
1621  * eapol_sm_get_session_id - Get EAP Session-Id
1622  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1623  * @len: Pointer to variable that will be set to number of bytes in the session
1624  * Returns: Pointer to the EAP Session-Id or %NULL on failure
1625  *
1626  * The Session-Id is available only after a successful authentication.
1627  */
1628 const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len)
1629 {
1630         if (sm == NULL || !eap_key_available(sm->eap)) {
1631                 wpa_printf(MSG_DEBUG, "EAPOL: EAP Session-Id not available");
1632                 return NULL;
1633         }
1634         return eap_get_eapSessionId(sm->eap, len);
1635 }
1636
1637
1638 /**
1639  * eapol_sm_notify_logoff - Notification of logon/logoff commands
1640  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1641  * @logoff: Whether command was logoff
1642  *
1643  * Notify EAPOL state machines that user requested logon/logoff.
1644  */
1645 void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
1646 {
1647         if (sm) {
1648                 sm->userLogoff = logoff;
1649                 if (!logoff) {
1650                         /* If there is a delayed txStart queued, start now. */
1651                         sm->startWhen = 0;
1652                 }
1653                 eapol_sm_step(sm);
1654         }
1655 }
1656
1657
1658 /**
1659  * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
1660  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1661  *
1662  * Notify EAPOL state machines that PMKSA caching was successful. This is used
1663  * to move EAPOL and EAP state machines into authenticated/successful state.
1664  */
1665 void eapol_sm_notify_cached(struct eapol_sm *sm)
1666 {
1667         if (sm == NULL)
1668                 return;
1669         wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
1670         sm->eapSuccess = TRUE;
1671         eap_notify_success(sm->eap);
1672         eapol_sm_step(sm);
1673 }
1674
1675
1676 /**
1677  * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
1678  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1679  *
1680  * Notify EAPOL state machines if PMKSA caching is used.
1681  */
1682 void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm)
1683 {
1684         if (sm == NULL)
1685                 return;
1686         wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
1687         sm->cached_pmk = TRUE;
1688 }
1689
1690
1691 static void eapol_sm_abort_cached(struct eapol_sm *sm)
1692 {
1693         wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
1694                    "doing full EAP authentication");
1695         if (sm == NULL)
1696                 return;
1697         sm->cached_pmk = FALSE;
1698         sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
1699         eapol_sm_set_port_unauthorized(sm);
1700
1701         /* Make sure we do not start sending EAPOL-Start frames first, but
1702          * instead move to RESTART state to start EAPOL authentication. */
1703         sm->startWhen = 3;
1704         eapol_enable_timer_tick(sm);
1705
1706         if (sm->ctx->aborted_cached)
1707                 sm->ctx->aborted_cached(sm->ctx->ctx);
1708 }
1709
1710
1711 /**
1712  * eapol_sm_register_scard_ctx - Notification of smart card context
1713  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1714  * @ctx: Context data for smart card operations
1715  *
1716  * Notify EAPOL state machines of context data for smart card operations. This
1717  * context data will be used as a parameter for scard_*() functions.
1718  */
1719 void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
1720 {
1721         if (sm) {
1722                 sm->ctx->scard_ctx = ctx;
1723                 eap_register_scard_ctx(sm->eap, ctx);
1724         }
1725 }
1726
1727
1728 /**
1729  * eapol_sm_notify_portControl - Notification of portControl changes
1730  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1731  * @portControl: New value for portControl variable
1732  *
1733  * Notify EAPOL state machines that portControl variable has changed.
1734  */
1735 void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
1736 {
1737         if (sm == NULL)
1738                 return;
1739         wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
1740                    "portControl=%s", eapol_port_control(portControl));
1741         sm->portControl = portControl;
1742         eapol_sm_step(sm);
1743 }
1744
1745
1746 /**
1747  * eapol_sm_notify_ctrl_attached - Notification of attached monitor
1748  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1749  *
1750  * Notify EAPOL state machines that a monitor was attached to the control
1751  * interface to trigger re-sending of pending requests for user input.
1752  */
1753 void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
1754 {
1755         if (sm == NULL)
1756                 return;
1757         eap_sm_notify_ctrl_attached(sm->eap);
1758 }
1759
1760
1761 /**
1762  * eapol_sm_notify_ctrl_response - Notification of received user input
1763  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1764  *
1765  * Notify EAPOL state machines that a control response, i.e., user
1766  * input, was received in order to trigger retrying of a pending EAP request.
1767  */
1768 void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
1769 {
1770         if (sm == NULL)
1771                 return;
1772         if (sm->eapReqData && !sm->eapReq) {
1773                 wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
1774                            "input) notification - retrying pending EAP "
1775                            "Request");
1776                 sm->eapolEap = TRUE;
1777                 sm->eapReq = TRUE;
1778                 eapol_sm_step(sm);
1779         }
1780 }
1781
1782
1783 /**
1784  * eapol_sm_request_reauth - Request reauthentication
1785  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1786  *
1787  * This function can be used to request EAPOL reauthentication, e.g., when the
1788  * current PMKSA entry is nearing expiration.
1789  */
1790 void eapol_sm_request_reauth(struct eapol_sm *sm)
1791 {
1792         if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
1793                 return;
1794         eapol_sm_txStart(sm);
1795 }
1796
1797
1798 /**
1799  * eapol_sm_notify_lower_layer_success - Notification of lower layer success
1800  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1801  * @in_eapol_sm: Whether the caller is already running inside EAPOL state
1802  * machine loop (eapol_sm_step())
1803  *
1804  * Notify EAPOL (and EAP) state machines that a lower layer has detected a
1805  * successful authentication. This is used to recover from dropped EAP-Success
1806  * messages.
1807  */
1808 void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
1809 {
1810         if (sm == NULL)
1811                 return;
1812         eap_notify_lower_layer_success(sm->eap);
1813         if (!in_eapol_sm)
1814                 eapol_sm_step(sm);
1815 }
1816
1817
1818 /**
1819  * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
1820  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
1821  */
1822 void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1823 {
1824         if (sm)
1825                 eap_invalidate_cached_session(sm->eap);
1826 }
1827
1828
1829 static struct eap_peer_config * eapol_sm_get_config(void *ctx)
1830 {
1831         struct eapol_sm *sm = ctx;
1832         return sm ? sm->config : NULL;
1833 }
1834
1835
1836 static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
1837 {
1838         struct eapol_sm *sm = ctx;
1839         if (sm == NULL || sm->eapReqData == NULL)
1840                 return NULL;
1841
1842         return sm->eapReqData;
1843 }
1844
1845
1846 static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
1847 {
1848         struct eapol_sm *sm = ctx;
1849         if (sm == NULL)
1850                 return FALSE;
1851         switch (variable) {
1852         case EAPOL_eapSuccess:
1853                 return sm->eapSuccess;
1854         case EAPOL_eapRestart:
1855                 return sm->eapRestart;
1856         case EAPOL_eapFail:
1857                 return sm->eapFail;
1858         case EAPOL_eapResp:
1859                 return sm->eapResp;
1860         case EAPOL_eapNoResp:
1861                 return sm->eapNoResp;
1862         case EAPOL_eapReq:
1863                 return sm->eapReq;
1864         case EAPOL_portEnabled:
1865                 return sm->portEnabled;
1866         case EAPOL_altAccept:
1867                 return sm->altAccept;
1868         case EAPOL_altReject:
1869                 return sm->altReject;
1870         case EAPOL_eapTriggerStart:
1871                 return sm->eapTriggerStart;
1872         }
1873         return FALSE;
1874 }
1875
1876
1877 static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
1878                               Boolean value)
1879 {
1880         struct eapol_sm *sm = ctx;
1881         if (sm == NULL)
1882                 return;
1883         switch (variable) {
1884         case EAPOL_eapSuccess:
1885                 sm->eapSuccess = value;
1886                 break;
1887         case EAPOL_eapRestart:
1888                 sm->eapRestart = value;
1889                 break;
1890         case EAPOL_eapFail:
1891                 sm->eapFail = value;
1892                 break;
1893         case EAPOL_eapResp:
1894                 sm->eapResp = value;
1895                 break;
1896         case EAPOL_eapNoResp:
1897                 sm->eapNoResp = value;
1898                 break;
1899         case EAPOL_eapReq:
1900                 sm->eapReq = value;
1901                 break;
1902         case EAPOL_portEnabled:
1903                 sm->portEnabled = value;
1904                 break;
1905         case EAPOL_altAccept:
1906                 sm->altAccept = value;
1907                 break;
1908         case EAPOL_altReject:
1909                 sm->altReject = value;
1910                 break;
1911         case EAPOL_eapTriggerStart:
1912                 sm->eapTriggerStart = value;
1913                 break;
1914         }
1915 }
1916
1917
1918 static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
1919 {
1920         struct eapol_sm *sm = ctx;
1921         if (sm == NULL)
1922                 return 0;
1923         switch (variable) {
1924         case EAPOL_idleWhile:
1925                 return sm->idleWhile;
1926         }
1927         return 0;
1928 }
1929
1930
1931 static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
1932                              unsigned int value)
1933 {
1934         struct eapol_sm *sm = ctx;
1935         if (sm == NULL)
1936                 return;
1937         switch (variable) {
1938         case EAPOL_idleWhile:
1939                 sm->idleWhile = value;
1940                 if (sm->idleWhile > 0)
1941                         eapol_enable_timer_tick(sm);
1942                 break;
1943         }
1944 }
1945
1946
1947 static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
1948 {
1949 #ifndef CONFIG_NO_CONFIG_BLOBS
1950         struct eapol_sm *sm = ctx;
1951         if (sm && sm->ctx && sm->ctx->set_config_blob)
1952                 sm->ctx->set_config_blob(sm->ctx->ctx, blob);
1953 #endif /* CONFIG_NO_CONFIG_BLOBS */
1954 }
1955
1956
1957 static const struct wpa_config_blob *
1958 eapol_sm_get_config_blob(void *ctx, const char *name)
1959 {
1960 #ifndef CONFIG_NO_CONFIG_BLOBS
1961         struct eapol_sm *sm = ctx;
1962         if (sm && sm->ctx && sm->ctx->get_config_blob)
1963                 return sm->ctx->get_config_blob(sm->ctx->ctx, name);
1964         else
1965                 return NULL;
1966 #else /* CONFIG_NO_CONFIG_BLOBS */
1967         return NULL;
1968 #endif /* CONFIG_NO_CONFIG_BLOBS */
1969 }
1970
1971
1972 static void eapol_sm_notify_pending(void *ctx)
1973 {
1974         struct eapol_sm *sm = ctx;
1975         if (sm == NULL)
1976                 return;
1977         if (sm->eapReqData && !sm->eapReq) {
1978                 wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
1979                            "state machine - retrying pending EAP Request");
1980                 sm->eapolEap = TRUE;
1981                 sm->eapReq = TRUE;
1982                 eapol_sm_step(sm);
1983         }
1984 }
1985
1986
1987 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
1988 static void eapol_sm_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
1989                                       const char *txt)
1990 {
1991         struct eapol_sm *sm = ctx;
1992         wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
1993         if (sm->ctx->eap_param_needed)
1994                 sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
1995 }
1996 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1997 #define eapol_sm_eap_param_needed NULL
1998 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
1999
2000 static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
2001                                  const char *altsubject[],
2002                                  int num_altsubject, const char *cert_hash,
2003                                  const struct wpabuf *cert)
2004 {
2005         struct eapol_sm *sm = ctx;
2006         if (sm->ctx->cert_cb)
2007                 sm->ctx->cert_cb(sm->ctx->ctx, depth, subject, altsubject,
2008                                  num_altsubject, cert_hash, cert);
2009 }
2010
2011
2012 static void eapol_sm_notify_status(void *ctx, const char *status,
2013                                    const char *parameter)
2014 {
2015         struct eapol_sm *sm = ctx;
2016
2017         if (sm->ctx->status_cb)
2018                 sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
2019 }
2020
2021
2022 static void eapol_sm_notify_eap_error(void *ctx, int error_code)
2023 {
2024         struct eapol_sm *sm = ctx;
2025
2026         if (sm->ctx->eap_error_cb)
2027                 sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
2028 }
2029
2030
2031 #ifdef CONFIG_EAP_PROXY
2032
2033 static void eapol_sm_eap_proxy_cb(void *ctx)
2034 {
2035         struct eapol_sm *sm = ctx;
2036
2037         if (sm->ctx->eap_proxy_cb)
2038                 sm->ctx->eap_proxy_cb(sm->ctx->ctx);
2039 }
2040
2041
2042 static void
2043 eapol_sm_eap_proxy_notify_sim_status(void *ctx,
2044                                      enum eap_proxy_sim_state sim_state)
2045 {
2046         struct eapol_sm *sm = ctx;
2047
2048         if (sm->ctx->eap_proxy_notify_sim_status)
2049                 sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state);
2050 }
2051
2052 #endif /* CONFIG_EAP_PROXY */
2053
2054
2055 static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
2056 {
2057         struct eapol_sm *sm = ctx;
2058
2059         if (sm->ctx->set_anon_id)
2060                 sm->ctx->set_anon_id(sm->ctx->ctx, id, len);
2061 }
2062
2063
2064 static const struct eapol_callbacks eapol_cb =
2065 {
2066         eapol_sm_get_config,
2067         eapol_sm_get_bool,
2068         eapol_sm_set_bool,
2069         eapol_sm_get_int,
2070         eapol_sm_set_int,
2071         eapol_sm_get_eapReqData,
2072         eapol_sm_set_config_blob,
2073         eapol_sm_get_config_blob,
2074         eapol_sm_notify_pending,
2075         eapol_sm_eap_param_needed,
2076         eapol_sm_notify_cert,
2077         eapol_sm_notify_status,
2078         eapol_sm_notify_eap_error,
2079 #ifdef CONFIG_EAP_PROXY
2080         eapol_sm_eap_proxy_cb,
2081         eapol_sm_eap_proxy_notify_sim_status,
2082         eapol_sm_get_eap_proxy_imsi,
2083 #endif /* CONFIG_EAP_PROXY */
2084         eapol_sm_set_anon_id
2085 };
2086
2087
2088 /**
2089  * eapol_sm_init - Initialize EAPOL state machine
2090  * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
2091  * and EAPOL state machine will free it in eapol_sm_deinit()
2092  * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
2093  *
2094  * Allocate and initialize an EAPOL state machine.
2095  */
2096 struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
2097 {
2098         struct eapol_sm *sm;
2099         struct eap_config conf;
2100         sm = os_zalloc(sizeof(*sm));
2101         if (sm == NULL)
2102                 return NULL;
2103         sm->ctx = ctx;
2104
2105         sm->portControl = Auto;
2106
2107         /* Supplicant PAE state machine */
2108         sm->heldPeriod = 60;
2109         sm->startPeriod = 30;
2110         sm->maxStart = 3;
2111
2112         /* Supplicant Backend state machine */
2113         sm->authPeriod = 30;
2114
2115         os_memset(&conf, 0, sizeof(conf));
2116         conf.opensc_engine_path = ctx->opensc_engine_path;
2117         conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
2118         conf.pkcs11_module_path = ctx->pkcs11_module_path;
2119         conf.openssl_ciphers = ctx->openssl_ciphers;
2120         conf.wps = ctx->wps;
2121         conf.cert_in_cb = ctx->cert_in_cb;
2122
2123         sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
2124         if (sm->eap == NULL) {
2125                 os_free(sm);
2126                 return NULL;
2127         }
2128
2129 #ifdef CONFIG_EAP_PROXY
2130         sm->use_eap_proxy = FALSE;
2131         sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
2132         if (sm->eap_proxy == NULL) {
2133                 wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
2134         }
2135 #endif /* CONFIG_EAP_PROXY */
2136
2137         /* Initialize EAPOL state machines */
2138         sm->force_authorized_update = TRUE;
2139         sm->initialize = TRUE;
2140         eapol_sm_step(sm);
2141         sm->initialize = FALSE;
2142         eapol_sm_step(sm);
2143
2144         sm->timer_tick_enabled = 1;
2145         eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
2146
2147         return sm;
2148 }
2149
2150
2151 /**
2152  * eapol_sm_deinit - Deinitialize EAPOL state machine
2153  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
2154  *
2155  * Deinitialize and free EAPOL state machine.
2156  */
2157 void eapol_sm_deinit(struct eapol_sm *sm)
2158 {
2159         if (sm == NULL)
2160                 return;
2161         eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
2162         eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
2163         eap_peer_sm_deinit(sm->eap);
2164 #ifdef CONFIG_EAP_PROXY
2165         eap_proxy_deinit(sm->eap_proxy);
2166 #endif /* CONFIG_EAP_PROXY */
2167         os_free(sm->last_rx_key);
2168         wpabuf_free(sm->eapReqData);
2169         os_free(sm->ctx);
2170         os_free(sm);
2171 }
2172
2173
2174 void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm,
2175                              struct ext_password_data *ext)
2176 {
2177         if (sm && sm->eap)
2178                 eap_sm_set_ext_pw_ctx(sm->eap, ext);
2179 }
2180
2181
2182 int eapol_sm_failed(struct eapol_sm *sm)
2183 {
2184         if (sm == NULL)
2185                 return 0;
2186         return !sm->eapSuccess && sm->eapFail;
2187 }
2188
2189
2190 #ifdef CONFIG_EAP_PROXY
2191 int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len)
2192 {
2193         struct eapol_sm *sm = ctx;
2194
2195         if (sm->eap_proxy == NULL)
2196                 return -1;
2197         return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len);
2198 }
2199 #endif /* CONFIG_EAP_PROXY */
2200
2201
2202 void eapol_sm_erp_flush(struct eapol_sm *sm)
2203 {
2204         if (sm)
2205                 eap_peer_erp_free_keys(sm->eap);
2206 }
2207
2208
2209 struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm)
2210 {
2211 #ifdef CONFIG_ERP
2212         if (!sm)
2213                 return NULL;
2214         return eap_peer_build_erp_reauth_start(sm->eap, 0);
2215 #else /* CONFIG_ERP */
2216         return NULL;
2217 #endif /* CONFIG_ERP */
2218 }
2219
2220
2221 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
2222                                  size_t len)
2223 {
2224 #ifdef CONFIG_ERP
2225         if (!sm)
2226                 return;
2227         eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
2228 #endif /* CONFIG_ERP */
2229 }
2230
2231
2232 int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
2233 {
2234 #ifdef CONFIG_ERP
2235         if (!sm)
2236                 return -1;
2237         return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
2238 #else /* CONFIG_ERP */
2239         return -1;
2240 #endif /* CONFIG_ERP */
2241 }
2242
2243
2244 int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
2245                           const u8 **username, size_t *username_len,
2246                           const u8 **realm, size_t *realm_len,
2247                           u16 *erp_next_seq_num, const u8 **rrk,
2248                           size_t *rrk_len)
2249 {
2250 #ifdef CONFIG_ERP
2251         if (!sm)
2252                 return -1;
2253         return eap_peer_get_erp_info(sm->eap, config, username, username_len,
2254                                      realm, realm_len, erp_next_seq_num, rrk,
2255                                      rrk_len);
2256 #else /* CONFIG_ERP */
2257         return -1;
2258 #endif /* CONFIG_ERP */
2259 }