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