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