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 */
36struct 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
159struct 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
188static void eapol_sm_txLogoff(struct eapol_sm *sm);
189static void eapol_sm_txStart(struct eapol_sm *sm);
190static void eapol_sm_processKey(struct eapol_sm *sm);
191static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
192static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
193static void eapol_sm_abortSupp(struct eapol_sm *sm);
194static void eapol_sm_abort_cached(struct eapol_sm *sm);
195static 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 */
200static 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
230SM_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
239SM_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
253SM_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
276SM_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
289SM_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
298SM_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
306SM_STATE(SUPP_PAE, RESTART)
307{
308	SM_ENTRY(SUPP_PAE, RESTART);
309	sm->eapRestart = TRUE;
310}
311
312
313SM_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
321SM_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
330SM_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
415SM_STATE(KEY_RX, NO_KEY_RECEIVE)
416{
417	SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
418}
419
420
421SM_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
429SM_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
448SM_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
457SM_STATE(SUPP_BE, RESPONSE)
458{
459	SM_ENTRY(SUPP_BE, RESPONSE);
460	eapol_sm_txSuppRsp(sm);
461	sm->eapResp = FALSE;
462}
463
464
465SM_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
479SM_STATE(SUPP_BE, FAIL)
480{
481	SM_ENTRY(SUPP_BE, FAIL);
482	sm->suppFail = TRUE;
483}
484
485
486SM_STATE(SUPP_BE, TIMEOUT)
487{
488	SM_ENTRY(SUPP_BE, TIMEOUT);
489	sm->suppTimeout = TRUE;
490}
491
492
493SM_STATE(SUPP_BE, IDLE)
494{
495	SM_ENTRY(SUPP_BE, IDLE);
496	sm->suppStart = FALSE;
497	sm->initial_req = TRUE;
498}
499
500
501SM_STATE(SUPP_BE, INITIALIZE)
502{
503	SM_ENTRY(SUPP_BE, INITIALIZE);
504	eapol_sm_abortSupp(sm);
505	sm->suppAbort = FALSE;
506}
507
508
509SM_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
519SM_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
591static 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
601static 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
614struct eap_key_data {
615	u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
616	u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
617};
618
619
620static 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
783static 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
793static 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
822static 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
834static 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 */
848void 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
883static 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
906static 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
931static 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)
942static 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 */
969void 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 */
999int 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 */
1051int 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 */
1121int 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 state machine about transmitted EAPOL packet from an external
1218 * component, e.g., WPA. This will update the statistics.
1219 */
1220void 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 state machine about new portEnabled value.
1233 */
1234void 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 state machine about new portValid value.
1251 */
1252void 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 the EAPOL state 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 */
1274void 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 state machine that external event has forced EAP state to
1294 * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
1295 */
1296void 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 state 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 */
1320void 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 */
1353int 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 */
1377void 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 */
1393void 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 */
1410void 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
1424static 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 */
1451void 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 */
1467void 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 */
1485void 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 */
1500void 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 */
1522void 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 */
1538void 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 */
1550void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
1551{
1552	if (sm)
1553		eap_invalidate_cached_session(sm->eap);
1554}
1555
1556
1557static 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
1564static 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
1577static 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
1606static 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
1644static 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
1657static 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
1671static 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
1679static const struct wpa_config_blob *
1680eapol_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
1690static 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
1705static 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 */
1727struct 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 */
1775void 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}
1787