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