Home | History | Annotate | 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 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    264 SM_STATE(CP, READY)
    265 {
    266 	SM_ENTRY(CP, READY);
    267 
    268 	ieee802_1x_kay_enable_new_info(sm->kay);
    269 }
    270 
    271 
    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 
    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 
    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 
    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  */
    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  */
    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 
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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
    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