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