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