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