• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * IEEE 802.1X-2010 Controlled Port of PAE state machine - CP state machine
3  * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/defs.h"
14 #include "common/ieee802_1x_defs.h"
15 #include "utils/state_machine.h"
16 #include "ieee802_1x_kay.h"
17 #include "ieee802_1x_secy_ops.h"
18 #include "pae/ieee802_1x_cp.h"
19 
20 #define STATE_MACHINE_DATA struct ieee802_1x_cp_sm
21 #define STATE_MACHINE_DEBUG_PREFIX "CP"
22 
23 static u64 default_cs_id = CS_ID_GCM_AES_128;
24 
25 /* The variable defined in clause 12 in IEEE Std 802.1X-2010 */
26 enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE };
27 
28 struct ieee802_1x_cp_sm {
29 	enum cp_states {
30 		CP_BEGIN, CP_INIT, CP_CHANGE, CP_ALLOWED, CP_AUTHENTICATED,
31 		CP_SECURED, CP_RECEIVE, CP_RECEIVING, CP_READY, CP_TRANSMIT,
32 		CP_TRANSMITTING, CP_ABANDON, CP_RETIRE
33 	} CP_state;
34 	Boolean changed;
35 
36 	/* CP -> Client */
37 	Boolean port_valid;
38 
39 	/* Logon -> CP */
40 	enum connect_type connect;
41 	u8 *authorization_data;
42 
43 	/* KaY -> CP */
44 	Boolean chgd_server; /* clear by CP */
45 	Boolean elected_self;
46 	u8 *authorization_data1;
47 	enum confidentiality_offset cipher_offset;
48 	u64 cipher_suite;
49 	Boolean new_sak; /* clear by CP */
50 	struct ieee802_1x_mka_ki distributed_ki;
51 	u8 distributed_an;
52 	Boolean using_receive_sas;
53 	Boolean all_receiving;
54 	Boolean server_transmitting;
55 	Boolean using_transmit_sa;
56 
57 	/* CP -> KaY */
58 	struct ieee802_1x_mka_ki *lki;
59 	u8 lan;
60 	Boolean ltx;
61 	Boolean lrx;
62 	struct ieee802_1x_mka_ki *oki;
63 	u8 oan;
64 	Boolean otx;
65 	Boolean orx;
66 
67 	/* CP -> SecY */
68 	Boolean protect_frames;
69 	enum validate_frames validate_frames;
70 
71 	Boolean replay_protect;
72 	u32 replay_window;
73 
74 	u64 current_cipher_suite;
75 	enum confidentiality_offset confidentiality_offset;
76 	Boolean controlled_port_enabled;
77 
78 	/* SecY -> CP */
79 	Boolean port_enabled; /* SecY->CP */
80 
81 	/* private */
82 	u32 transmit_when;
83 	u32 transmit_delay;
84 	u32 retire_when;
85 	u32 retire_delay;
86 
87 	/* not defined IEEE Std 802.1X-2010 */
88 	struct ieee802_1x_kay *kay;
89 };
90 
91 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
92 					      void *timeout_ctx);
93 static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx,
94 						void *timeout_ctx);
95 
96 
changed_cipher(struct ieee802_1x_cp_sm * sm)97 static int changed_cipher(struct ieee802_1x_cp_sm *sm)
98 {
99 	return sm->confidentiality_offset != sm->cipher_offset ||
100 		sm->current_cipher_suite != sm->cipher_suite;
101 }
102 
103 
changed_connect(struct ieee802_1x_cp_sm * sm)104 static int changed_connect(struct ieee802_1x_cp_sm *sm)
105 {
106 	return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm);
107 }
108 
109 
SM_STATE(CP,INIT)110 SM_STATE(CP, INIT)
111 {
112 	SM_ENTRY(CP, INIT);
113 
114 	sm->controlled_port_enabled = FALSE;
115 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
116 
117 	sm->port_valid = FALSE;
118 
119 	os_free(sm->lki);
120 	sm->lki = NULL;
121 	sm->ltx = FALSE;
122 	sm->lrx = FALSE;
123 
124 	os_free(sm->oki);
125 	sm->oki = NULL;
126 	sm->otx = FALSE;
127 	sm->orx = FALSE;
128 
129 	sm->port_enabled = TRUE;
130 	sm->chgd_server = FALSE;
131 }
132 
133 
SM_STATE(CP,CHANGE)134 SM_STATE(CP, CHANGE)
135 {
136 	SM_ENTRY(CP, CHANGE);
137 
138 	sm->port_valid = FALSE;
139 	sm->controlled_port_enabled = FALSE;
140 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
141 
142 	if (sm->lki)
143 		ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
144 	if (sm->oki)
145 		ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
146 }
147 
148 
SM_STATE(CP,ALLOWED)149 SM_STATE(CP, ALLOWED)
150 {
151 	SM_ENTRY(CP, ALLOWED);
152 
153 	sm->protect_frames = FALSE;
154 	sm->replay_protect = FALSE;
155 	sm->validate_frames = Checked;
156 
157 	sm->port_valid = FALSE;
158 	sm->controlled_port_enabled = TRUE;
159 
160 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
161 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
162 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
163 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
164 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
165 }
166 
167 
SM_STATE(CP,AUTHENTICATED)168 SM_STATE(CP, AUTHENTICATED)
169 {
170 	SM_ENTRY(CP, AUTHENTICATED);
171 
172 	sm->protect_frames = FALSE;
173 	sm->replay_protect = FALSE;
174 	sm->validate_frames = Checked;
175 
176 	sm->port_valid = FALSE;
177 	sm->controlled_port_enabled = TRUE;
178 
179 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
180 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
181 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
182 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
183 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
184 }
185 
186 
SM_STATE(CP,SECURED)187 SM_STATE(CP, SECURED)
188 {
189 	SM_ENTRY(CP, SECURED);
190 
191 	sm->chgd_server = FALSE;
192 
193 	sm->protect_frames = sm->kay->macsec_protect;
194 	sm->replay_protect = sm->kay->macsec_replay_protect;
195 	sm->validate_frames = sm->kay->macsec_validate;
196 
197 	/* NOTE: now no other than default cipher suite (AES-GCM-128) */
198 	sm->current_cipher_suite = sm->cipher_suite;
199 	secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
200 
201 	sm->confidentiality_offset = sm->cipher_offset;
202 
203 	sm->port_valid = TRUE;
204 
205 	secy_cp_control_confidentiality_offset(sm->kay,
206 					       sm->confidentiality_offset);
207 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
208 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
209 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
210 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
211 }
212 
213 
SM_STATE(CP,RECEIVE)214 SM_STATE(CP, RECEIVE)
215 {
216 	SM_ENTRY(CP, RECEIVE);
217 	/* RECEIVE state machine not keep with Figure 12-2 in
218 	 * IEEE Std 802.1X-2010 */
219 	sm->oki = sm->lki;
220 	sm->oan = sm->lan;
221 	sm->otx = sm->ltx;
222 	sm->orx = sm->lrx;
223 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
224 				       sm->otx, sm->orx);
225 
226 	sm->lki = os_malloc(sizeof(*sm->lki));
227 	if (!sm->lki) {
228 		wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
229 		return;
230 	}
231 	os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
232 	sm->lan = sm->distributed_an;
233 	sm->ltx = FALSE;
234 	sm->lrx = FALSE;
235 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
236 					  sm->ltx, sm->lrx);
237 	ieee802_1x_kay_create_sas(sm->kay, sm->lki);
238 	ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
239 	sm->new_sak = FALSE;
240 	sm->all_receiving = FALSE;
241 }
242 
243 
SM_STATE(CP,RECEIVING)244 SM_STATE(CP, RECEIVING)
245 {
246 	SM_ENTRY(CP, RECEIVING);
247 
248 	sm->lrx = TRUE;
249 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
250 					  sm->ltx, sm->lrx);
251 	sm->transmit_when = sm->transmit_delay;
252 	eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
253 	eloop_register_timeout(sm->transmit_when / 1000, 0,
254 			       ieee802_1x_cp_transmit_when_timeout, sm, NULL);
255 	/* the electedSelf have been set before CP entering to RECEIVING
256 	 * but the CP will transmit from RECEIVING to READY under
257 	 * the !electedSelf when KaY is not key server */
258 	ieee802_1x_cp_sm_step(sm);
259 	sm->using_receive_sas = FALSE;
260 	sm->server_transmitting = FALSE;
261 }
262 
263 
SM_STATE(CP,READY)264 SM_STATE(CP, READY)
265 {
266 	SM_ENTRY(CP, READY);
267 
268 	ieee802_1x_kay_enable_new_info(sm->kay);
269 }
270 
271 
SM_STATE(CP,TRANSMIT)272 SM_STATE(CP, TRANSMIT)
273 {
274 	SM_ENTRY(CP, TRANSMIT);
275 
276 	sm->controlled_port_enabled = TRUE;
277 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
278 	sm->ltx = TRUE;
279 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
280 					  sm->ltx, sm->lrx);
281 	ieee802_1x_kay_enable_tx_sas(sm->kay,  sm->lki);
282 	sm->all_receiving = FALSE;
283 	sm->server_transmitting = FALSE;
284 }
285 
286 
SM_STATE(CP,TRANSMITTING)287 SM_STATE(CP, TRANSMITTING)
288 {
289 	SM_ENTRY(CP, TRANSMITTING);
290 	sm->retire_when = sm->orx ? sm->retire_delay : 0;
291 	sm->otx = FALSE;
292 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
293 				       sm->otx, sm->orx);
294 	ieee802_1x_kay_enable_new_info(sm->kay);
295 	eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
296 	eloop_register_timeout(sm->retire_when / 1000, 0,
297 			       ieee802_1x_cp_retire_when_timeout, sm, NULL);
298 	sm->using_transmit_sa = FALSE;
299 }
300 
301 
SM_STATE(CP,ABANDON)302 SM_STATE(CP, ABANDON)
303 {
304 	SM_ENTRY(CP, ABANDON);
305 	sm->lrx = FALSE;
306 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
307 					  sm->ltx, sm->lrx);
308 	ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
309 
310 	os_free(sm->lki);
311 	sm->lki = NULL;
312 	ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
313 					  sm->ltx, sm->lrx);
314 	sm->new_sak = FALSE;
315 }
316 
317 
SM_STATE(CP,RETIRE)318 SM_STATE(CP, RETIRE)
319 {
320 	SM_ENTRY(CP, RETIRE);
321 	/* RETIRE state machine not keep with Figure 12-2 in
322 	 * IEEE Std 802.1X-2010 */
323 	os_free(sm->oki);
324 	sm->oki = NULL;
325 	sm->orx = FALSE;
326 	sm->otx = FALSE;
327 	ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
328 				       sm->otx, sm->orx);
329 }
330 
331 
332 /**
333  * CP state machine handler entry
334  */
SM_STEP(CP)335 SM_STEP(CP)
336 {
337 	if (!sm->port_enabled)
338 		SM_ENTER(CP, INIT);
339 
340 	switch (sm->CP_state) {
341 	case CP_BEGIN:
342 		SM_ENTER(CP, INIT);
343 		break;
344 
345 	case CP_INIT:
346 		SM_ENTER(CP, CHANGE);
347 		break;
348 
349 	case CP_CHANGE:
350 		if (sm->connect == UNAUTHENTICATED)
351 			SM_ENTER(CP, ALLOWED);
352 		else if (sm->connect == AUTHENTICATED)
353 			SM_ENTER(CP, AUTHENTICATED);
354 		else if (sm->connect == SECURE)
355 			SM_ENTER(CP, SECURED);
356 		break;
357 
358 	case CP_ALLOWED:
359 		if (sm->connect != UNAUTHENTICATED)
360 			SM_ENTER(CP, CHANGE);
361 		break;
362 
363 	case CP_AUTHENTICATED:
364 		if (sm->connect != AUTHENTICATED)
365 			SM_ENTER(CP, CHANGE);
366 		break;
367 
368 	case CP_SECURED:
369 		if (changed_connect(sm))
370 			SM_ENTER(CP, CHANGE);
371 		else if (sm->new_sak)
372 			SM_ENTER(CP, RECEIVE);
373 		break;
374 
375 	case CP_RECEIVE:
376 		if (sm->using_receive_sas)
377 			SM_ENTER(CP, RECEIVING);
378 		break;
379 
380 	case CP_RECEIVING:
381 		if (sm->new_sak || changed_connect(sm))
382 			SM_ENTER(CP, ABANDON);
383 		if (!sm->elected_self)
384 			SM_ENTER(CP, READY);
385 		if (sm->elected_self &&
386 		    (sm->all_receiving || !sm->transmit_when))
387 			SM_ENTER(CP, TRANSMIT);
388 		break;
389 
390 	case CP_TRANSMIT:
391 		if (sm->using_transmit_sa)
392 			SM_ENTER(CP, TRANSMITTING);
393 		break;
394 
395 	case CP_TRANSMITTING:
396 		if (!sm->retire_when || changed_connect(sm))
397 			SM_ENTER(CP, RETIRE);
398 		break;
399 
400 	case CP_RETIRE:
401 		if (changed_connect(sm))
402 			SM_ENTER(CP, CHANGE);
403 		else if (sm->new_sak)
404 			SM_ENTER(CP, RECEIVE);
405 		break;
406 
407 	case CP_READY:
408 		if (sm->new_sak || changed_connect(sm))
409 			SM_ENTER(CP, RECEIVE);
410 		if (sm->server_transmitting)
411 			SM_ENTER(CP, TRANSMIT);
412 		break;
413 	case CP_ABANDON:
414 		if (changed_connect(sm))
415 			SM_ENTER(CP, RETIRE);
416 		else if (sm->new_sak)
417 			SM_ENTER(CP, RECEIVE);
418 		break;
419 	default:
420 		wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
421 		break;
422 	}
423 }
424 
425 
426 /**
427  * ieee802_1x_cp_sm_init -
428  */
ieee802_1x_cp_sm_init(struct ieee802_1x_kay * kay)429 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
430 {
431 	struct ieee802_1x_cp_sm *sm;
432 
433 	sm = os_zalloc(sizeof(*sm));
434 	if (sm == NULL) {
435 		wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
436 		return NULL;
437 	}
438 
439 	sm->kay = kay;
440 
441 	sm->port_valid = FALSE;
442 
443 	sm->chgd_server = FALSE;
444 
445 	sm->protect_frames = kay->macsec_protect;
446 	sm->validate_frames = kay->macsec_validate;
447 	sm->replay_protect = kay->macsec_replay_protect;
448 	sm->replay_window = kay->macsec_replay_window;
449 
450 	sm->controlled_port_enabled = FALSE;
451 
452 	sm->lki = NULL;
453 	sm->lrx = FALSE;
454 	sm->ltx = FALSE;
455 	sm->oki = NULL;
456 	sm->orx = FALSE;
457 	sm->otx = FALSE;
458 
459 	sm->current_cipher_suite = default_cs_id;
460 	sm->cipher_suite = default_cs_id;
461 	sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
462 	sm->confidentiality_offset = sm->cipher_offset;
463 	sm->transmit_delay = MKA_LIFE_TIME;
464 	sm->retire_delay = MKA_SAK_RETIRE_TIME;
465 	sm->CP_state = CP_BEGIN;
466 	sm->changed = FALSE;
467 	sm->authorization_data = NULL;
468 
469 	wpa_printf(MSG_DEBUG, "CP: state machine created");
470 
471 	secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
472 	secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
473 	secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
474 	secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
475 	secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
476 	secy_cp_control_confidentiality_offset(sm->kay,
477 					       sm->confidentiality_offset);
478 
479 	SM_ENTER(CP, INIT);
480 	SM_STEP_RUN(CP);
481 
482 	return sm;
483 }
484 
485 
ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm * sm)486 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
487 {
488 	enum cp_states prev_state;
489 	int i;
490 
491 	for (i = 0; i < 100; i++) {
492 		prev_state = sm->CP_state;
493 		SM_STEP_RUN(CP);
494 		if (prev_state == sm->CP_state)
495 			break;
496 	}
497 }
498 
499 
ieee802_1x_cp_step_cb(void * eloop_ctx,void * timeout_ctx)500 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
501 {
502 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
503 	ieee802_1x_cp_step_run(sm);
504 }
505 
506 
507 /**
508  * ieee802_1x_cp_sm_deinit -
509  */
ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm * sm)510 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
511 {
512 	wpa_printf(MSG_DEBUG, "CP: state machine removed");
513 	if (!sm)
514 		return;
515 
516 	eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
517 	eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
518 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
519 	os_free(sm->lki);
520 	os_free(sm->oki);
521 	os_free(sm->authorization_data);
522 	os_free(sm);
523 }
524 
525 
526 /**
527  * ieee802_1x_cp_connect_pending
528  */
ieee802_1x_cp_connect_pending(void * cp_ctx)529 void ieee802_1x_cp_connect_pending(void *cp_ctx)
530 {
531 	struct ieee802_1x_cp_sm *sm = cp_ctx;
532 
533 	sm->connect = PENDING;
534 }
535 
536 
537 /**
538  * ieee802_1x_cp_connect_unauthenticated
539  */
ieee802_1x_cp_connect_unauthenticated(void * cp_ctx)540 void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
541 {
542 	struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
543 
544 	sm->connect = UNAUTHENTICATED;
545 }
546 
547 
548 /**
549  * ieee802_1x_cp_connect_authenticated
550  */
ieee802_1x_cp_connect_authenticated(void * cp_ctx)551 void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
552 {
553 	struct ieee802_1x_cp_sm *sm = cp_ctx;
554 
555 	sm->connect = AUTHENTICATED;
556 }
557 
558 
559 /**
560  * ieee802_1x_cp_connect_secure
561  */
ieee802_1x_cp_connect_secure(void * cp_ctx)562 void ieee802_1x_cp_connect_secure(void *cp_ctx)
563 {
564 	struct ieee802_1x_cp_sm *sm = cp_ctx;
565 
566 	sm->connect = SECURE;
567 }
568 
569 
570 /**
571  * ieee802_1x_cp_set_chgdserver -
572  */
ieee802_1x_cp_signal_chgdserver(void * cp_ctx)573 void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
574 {
575 	struct ieee802_1x_cp_sm *sm = cp_ctx;
576 
577 	sm->chgd_server = TRUE;
578 }
579 
580 
581 /**
582  * ieee802_1x_cp_set_electedself -
583  */
ieee802_1x_cp_set_electedself(void * cp_ctx,Boolean status)584 void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
585 {
586 	struct ieee802_1x_cp_sm *sm = cp_ctx;
587 	sm->elected_self = status;
588 }
589 
590 
591 /**
592  * ieee802_1x_cp_set_authorizationdata -
593  */
ieee802_1x_cp_set_authorizationdata(void * cp_ctx,u8 * pdata,int len)594 void ieee802_1x_cp_set_authorizationdata(void *cp_ctx, u8 *pdata, int len)
595 {
596 	struct ieee802_1x_cp_sm *sm = cp_ctx;
597 	os_free(sm->authorization_data);
598 	sm->authorization_data = os_zalloc(len);
599 	if (sm->authorization_data)
600 		os_memcpy(sm->authorization_data, pdata, len);
601 }
602 
603 
604 /**
605  * ieee802_1x_cp_set_ciphersuite -
606  */
ieee802_1x_cp_set_ciphersuite(void * cp_ctx,u64 cs)607 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
608 {
609 	struct ieee802_1x_cp_sm *sm = cp_ctx;
610 	sm->cipher_suite = cs;
611 }
612 
613 
614 /**
615  * ieee802_1x_cp_set_offset -
616  */
ieee802_1x_cp_set_offset(void * cp_ctx,enum confidentiality_offset offset)617 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
618 {
619 	struct ieee802_1x_cp_sm *sm = cp_ctx;
620 	sm->cipher_offset = offset;
621 }
622 
623 
624 /**
625  * ieee802_1x_cp_signal_newsak -
626  */
ieee802_1x_cp_signal_newsak(void * cp_ctx)627 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
628 {
629 	struct ieee802_1x_cp_sm *sm = cp_ctx;
630 	sm->new_sak = TRUE;
631 }
632 
633 
634 /**
635  * ieee802_1x_cp_set_distributedki -
636  */
ieee802_1x_cp_set_distributedki(void * cp_ctx,const struct ieee802_1x_mka_ki * dki)637 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
638 				     const struct ieee802_1x_mka_ki *dki)
639 {
640 	struct ieee802_1x_cp_sm *sm = cp_ctx;
641 	os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
642 }
643 
644 
645 /**
646  * ieee802_1x_cp_set_distributedan -
647  */
ieee802_1x_cp_set_distributedan(void * cp_ctx,u8 an)648 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
649 {
650 	struct ieee802_1x_cp_sm *sm = cp_ctx;
651 	sm->distributed_an = an;
652 }
653 
654 
655 /**
656  * ieee802_1x_cp_set_usingreceivesas -
657  */
ieee802_1x_cp_set_usingreceivesas(void * cp_ctx,Boolean status)658 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
659 {
660 	struct ieee802_1x_cp_sm *sm = cp_ctx;
661 	sm->using_receive_sas = status;
662 }
663 
664 
665 /**
666  * ieee802_1x_cp_set_allreceiving -
667  */
ieee802_1x_cp_set_allreceiving(void * cp_ctx,Boolean status)668 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
669 {
670 	struct ieee802_1x_cp_sm *sm = cp_ctx;
671 	sm->all_receiving = status;
672 }
673 
674 
675 /**
676  * ieee802_1x_cp_set_servertransmitting -
677  */
ieee802_1x_cp_set_servertransmitting(void * cp_ctx,Boolean status)678 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
679 {
680 	struct ieee802_1x_cp_sm *sm = cp_ctx;
681 	sm->server_transmitting = status;
682 }
683 
684 
685 /**
686  * ieee802_1x_cp_set_usingtransmitsas -
687  */
ieee802_1x_cp_set_usingtransmitas(void * cp_ctx,Boolean status)688 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
689 {
690 	struct ieee802_1x_cp_sm *sm = cp_ctx;
691 	sm->using_transmit_sa = status;
692 }
693 
694 
695 /**
696  * ieee802_1x_cp_sm_step - Advance EAPOL state machines
697  * @sm: EAPOL state machine
698  *
699  * This function is called to advance CP state machines after any change
700  * that could affect their state.
701  */
ieee802_1x_cp_sm_step(void * cp_ctx)702 void ieee802_1x_cp_sm_step(void *cp_ctx)
703 {
704 	/*
705 	 * Run ieee802_1x_cp_step_run from a registered timeout
706 	 * to make sure that other possible timeouts/events are processed
707 	 * and to avoid long function call chains.
708 	 */
709 	struct ieee802_1x_cp_sm *sm = cp_ctx;
710 	eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
711 	eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
712 }
713 
714 
ieee802_1x_cp_retire_when_timeout(void * eloop_ctx,void * timeout_ctx)715 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
716 					      void *timeout_ctx)
717 {
718 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
719 	sm->retire_when = 0;
720 	ieee802_1x_cp_step_run(sm);
721 }
722 
723 
724 static void
ieee802_1x_cp_transmit_when_timeout(void * eloop_ctx,void * timeout_ctx)725 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
726 {
727 	struct ieee802_1x_cp_sm *sm = eloop_ctx;
728 	sm->transmit_when = 0;
729 	ieee802_1x_cp_step_run(sm);
730 }
731