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