OSDN Git Service

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