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