Home | History | Annotate | Line # | Download | only in pae
      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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    276 SM_STATE(CP, READY)
    277 {
    278 	SM_ENTRY(CP, READY);
    279 
    280 	ieee802_1x_kay_enable_new_info(sm->kay);
    281 }
    282 
    283 
    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 
    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 
    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 
    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  */
    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  */
    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 
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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
    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