2 * IEEE 802.1X-2010 Controlled Port of PAE state machine - CP state machine
3 * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
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"
20 #define STATE_MACHINE_DATA struct ieee802_1x_cp_sm
21 #define STATE_MACHINE_DEBUG_PREFIX "CP"
23 static u64 default_cs_id = CS_ID_GCM_AES_128;
25 /* The variable defined in clause 12 in IEEE Std 802.1X-2010 */
26 enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE };
28 struct ieee802_1x_cp_sm {
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
40 enum connect_type connect;
41 u8 *authorization_data;
44 Boolean chgd_server; /* clear by CP */
46 u8 *authorization_data1;
47 enum confidentiality_offset cipher_offset;
49 Boolean new_sak; /* clear by CP */
50 struct ieee802_1x_mka_ki distributed_ki;
52 Boolean using_receive_sas;
53 Boolean all_receiving;
54 Boolean server_transmitting;
55 Boolean using_transmit_sa;
58 struct ieee802_1x_mka_ki *lki;
62 struct ieee802_1x_mka_ki *oki;
68 Boolean protect_frames;
69 enum validate_frames validate_frames;
71 Boolean replay_protect;
74 u64 current_cipher_suite;
75 enum confidentiality_offset confidentiality_offset;
76 Boolean controlled_port_enabled;
79 Boolean port_enabled; /* SecY->CP */
87 /* not defined IEEE Std 802.1X-2010 */
88 struct ieee802_1x_kay *kay;
91 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
93 static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx,
97 static int changed_cipher(struct ieee802_1x_cp_sm *sm)
99 return sm->confidentiality_offset != sm->cipher_offset ||
100 sm->current_cipher_suite != sm->cipher_suite;
104 static int changed_connect(struct ieee802_1x_cp_sm *sm)
106 return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm);
114 sm->controlled_port_enabled = FALSE;
115 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
117 sm->port_valid = FALSE;
129 sm->port_enabled = TRUE;
130 sm->chgd_server = FALSE;
136 SM_ENTRY(CP, CHANGE);
138 sm->port_valid = FALSE;
139 sm->controlled_port_enabled = FALSE;
140 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
143 ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
145 ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
149 SM_STATE(CP, ALLOWED)
151 SM_ENTRY(CP, ALLOWED);
153 sm->protect_frames = FALSE;
154 sm->replay_protect = FALSE;
155 sm->validate_frames = Checked;
157 sm->port_valid = FALSE;
158 sm->controlled_port_enabled = TRUE;
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_validate_frames(sm->kay, sm->validate_frames);
163 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
167 SM_STATE(CP, AUTHENTICATED)
169 SM_ENTRY(CP, AUTHENTICATED);
171 sm->protect_frames = FALSE;
172 sm->replay_protect = FALSE;
173 sm->validate_frames = Checked;
175 sm->port_valid = FALSE;
176 sm->controlled_port_enabled = TRUE;
178 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
179 secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
180 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
181 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
185 SM_STATE(CP, SECURED)
187 SM_ENTRY(CP, SECURED);
189 sm->chgd_server = FALSE;
191 sm->protect_frames = sm->kay->macsec_protect;
192 sm->replay_protect = sm->kay->macsec_replay_protect;
193 sm->validate_frames = sm->kay->macsec_validate;
195 /* NOTE: now no other than default cipher suite (AES-GCM-128) */
196 sm->current_cipher_suite = sm->cipher_suite;
197 secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
199 sm->confidentiality_offset = sm->cipher_offset;
201 sm->port_valid = TRUE;
203 secy_cp_control_confidentiality_offset(sm->kay,
204 sm->confidentiality_offset);
205 secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
206 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
207 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
211 SM_STATE(CP, RECEIVE)
213 SM_ENTRY(CP, RECEIVE);
214 /* RECEIVE state machine not keep with Figure 12-2 in
215 * IEEE Std 802.1X-2010 */
220 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
223 sm->lki = os_malloc(sizeof(*sm->lki));
225 wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
228 os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
229 sm->lan = sm->distributed_an;
232 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
234 ieee802_1x_kay_create_sas(sm->kay, sm->lki);
235 ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
237 sm->all_receiving = FALSE;
241 SM_STATE(CP, RECEIVING)
243 SM_ENTRY(CP, RECEIVING);
246 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
248 sm->transmit_when = sm->transmit_delay;
249 eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
250 eloop_register_timeout(sm->transmit_when / 1000, 0,
251 ieee802_1x_cp_transmit_when_timeout, sm, NULL);
252 /* the electedSelf have been set before CP entering to RECEIVING
253 * but the CP will transmit from RECEIVING to READY under
254 * the !electedSelf when KaY is not key server */
255 ieee802_1x_cp_sm_step(sm);
256 sm->using_receive_sas = FALSE;
257 sm->server_transmitting = FALSE;
265 ieee802_1x_kay_enable_new_info(sm->kay);
269 SM_STATE(CP, TRANSMIT)
271 SM_ENTRY(CP, TRANSMIT);
273 sm->controlled_port_enabled = TRUE;
274 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
276 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
278 ieee802_1x_kay_enable_tx_sas(sm->kay, sm->lki);
279 sm->all_receiving = FALSE;
280 sm->server_transmitting = FALSE;
284 SM_STATE(CP, TRANSMITTING)
286 SM_ENTRY(CP, TRANSMITTING);
287 sm->retire_when = sm->orx ? sm->retire_delay : 0;
289 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
291 ieee802_1x_kay_enable_new_info(sm->kay);
292 eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
293 eloop_register_timeout(sm->retire_when / 1000, 0,
294 ieee802_1x_cp_retire_when_timeout, sm, NULL);
295 sm->using_transmit_sa = FALSE;
299 SM_STATE(CP, ABANDON)
301 SM_ENTRY(CP, ABANDON);
303 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
305 ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
309 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
317 SM_ENTRY(CP, RETIRE);
318 /* RETIRE state machine not keep with Figure 12-2 in
319 * IEEE Std 802.1X-2010 */
324 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
330 * CP state machine handler entry
334 if (!sm->port_enabled)
337 switch (sm->CP_state) {
343 SM_ENTER(CP, CHANGE);
347 if (sm->connect == UNAUTHENTICATED)
348 SM_ENTER(CP, ALLOWED);
349 else if (sm->connect == AUTHENTICATED)
350 SM_ENTER(CP, AUTHENTICATED);
351 else if (sm->connect == SECURE)
352 SM_ENTER(CP, SECURED);
356 if (sm->connect != UNAUTHENTICATED)
357 SM_ENTER(CP, CHANGE);
360 case CP_AUTHENTICATED:
361 if (sm->connect != AUTHENTICATED)
362 SM_ENTER(CP, CHANGE);
366 if (changed_connect(sm))
367 SM_ENTER(CP, CHANGE);
368 else if (sm->new_sak)
369 SM_ENTER(CP, RECEIVE);
373 if (sm->using_receive_sas)
374 SM_ENTER(CP, RECEIVING);
378 if (sm->new_sak || changed_connect(sm))
379 SM_ENTER(CP, ABANDON);
380 if (!sm->elected_self)
382 if (sm->elected_self &&
383 (sm->all_receiving || !sm->transmit_when))
384 SM_ENTER(CP, TRANSMIT);
388 if (sm->using_transmit_sa)
389 SM_ENTER(CP, TRANSMITTING);
392 case CP_TRANSMITTING:
393 if (!sm->retire_when || changed_connect(sm))
394 SM_ENTER(CP, RETIRE);
398 if (changed_connect(sm))
399 SM_ENTER(CP, CHANGE);
400 else if (sm->new_sak)
401 SM_ENTER(CP, RECEIVE);
405 if (sm->new_sak || changed_connect(sm))
406 SM_ENTER(CP, RECEIVE);
407 if (sm->server_transmitting)
408 SM_ENTER(CP, TRANSMIT);
411 if (changed_connect(sm))
412 SM_ENTER(CP, RETIRE);
413 else if (sm->new_sak)
414 SM_ENTER(CP, RECEIVE);
417 wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
424 * ieee802_1x_cp_sm_init -
426 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
428 struct ieee802_1x_cp_sm *sm;
430 sm = os_zalloc(sizeof(*sm));
432 wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
438 sm->port_valid = FALSE;
440 sm->chgd_server = FALSE;
442 sm->protect_frames = kay->macsec_protect;
443 sm->validate_frames = kay->macsec_validate;
444 sm->replay_protect = kay->macsec_replay_protect;
445 sm->replay_window = kay->macsec_replay_window;
447 sm->controlled_port_enabled = FALSE;
456 sm->current_cipher_suite = default_cs_id;
457 sm->cipher_suite = default_cs_id;
458 sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
459 sm->confidentiality_offset = sm->cipher_offset;
460 sm->transmit_delay = MKA_LIFE_TIME;
461 sm->retire_delay = MKA_SAK_RETIRE_TIME;
462 sm->CP_state = CP_BEGIN;
464 sm->authorization_data = NULL;
466 wpa_printf(MSG_DEBUG, "CP: state machine created");
468 secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
469 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
470 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
471 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
472 secy_cp_control_confidentiality_offset(sm->kay,
473 sm->confidentiality_offset);
482 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
484 enum cp_states prev_state;
487 for (i = 0; i < 100; i++) {
488 prev_state = sm->CP_state;
490 if (prev_state == sm->CP_state)
496 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
498 struct ieee802_1x_cp_sm *sm = eloop_ctx;
499 ieee802_1x_cp_step_run(sm);
504 * ieee802_1x_cp_sm_deinit -
506 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
508 wpa_printf(MSG_DEBUG, "CP: state machine removed");
512 eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
513 eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
514 eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
517 os_free(sm->authorization_data);
523 * ieee802_1x_cp_connect_pending
525 void ieee802_1x_cp_connect_pending(void *cp_ctx)
527 struct ieee802_1x_cp_sm *sm = cp_ctx;
529 sm->connect = PENDING;
534 * ieee802_1x_cp_connect_unauthenticated
536 void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
538 struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
540 sm->connect = UNAUTHENTICATED;
545 * ieee802_1x_cp_connect_authenticated
547 void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
549 struct ieee802_1x_cp_sm *sm = cp_ctx;
551 sm->connect = AUTHENTICATED;
556 * ieee802_1x_cp_connect_secure
558 void ieee802_1x_cp_connect_secure(void *cp_ctx)
560 struct ieee802_1x_cp_sm *sm = cp_ctx;
562 sm->connect = SECURE;
567 * ieee802_1x_cp_set_chgdserver -
569 void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
571 struct ieee802_1x_cp_sm *sm = cp_ctx;
573 sm->chgd_server = TRUE;
578 * ieee802_1x_cp_set_electedself -
580 void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
582 struct ieee802_1x_cp_sm *sm = cp_ctx;
583 sm->elected_self = status;
588 * ieee802_1x_cp_set_authorizationdata -
590 void ieee802_1x_cp_set_authorizationdata(void *cp_ctx, u8 *pdata, int len)
592 struct ieee802_1x_cp_sm *sm = cp_ctx;
593 os_free(sm->authorization_data);
594 sm->authorization_data = os_zalloc(len);
595 if (sm->authorization_data)
596 os_memcpy(sm->authorization_data, pdata, len);
601 * ieee802_1x_cp_set_ciphersuite -
603 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
605 struct ieee802_1x_cp_sm *sm = cp_ctx;
606 sm->cipher_suite = cs;
611 * ieee802_1x_cp_set_offset -
613 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
615 struct ieee802_1x_cp_sm *sm = cp_ctx;
616 sm->cipher_offset = offset;
621 * ieee802_1x_cp_signal_newsak -
623 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
625 struct ieee802_1x_cp_sm *sm = cp_ctx;
631 * ieee802_1x_cp_set_distributedki -
633 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
634 const struct ieee802_1x_mka_ki *dki)
636 struct ieee802_1x_cp_sm *sm = cp_ctx;
637 os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
642 * ieee802_1x_cp_set_distributedan -
644 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
646 struct ieee802_1x_cp_sm *sm = cp_ctx;
647 sm->distributed_an = an;
652 * ieee802_1x_cp_set_usingreceivesas -
654 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
656 struct ieee802_1x_cp_sm *sm = cp_ctx;
657 sm->using_receive_sas = status;
662 * ieee802_1x_cp_set_allreceiving -
664 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
666 struct ieee802_1x_cp_sm *sm = cp_ctx;
667 sm->all_receiving = status;
672 * ieee802_1x_cp_set_servertransmitting -
674 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
676 struct ieee802_1x_cp_sm *sm = cp_ctx;
677 sm->server_transmitting = status;
682 * ieee802_1x_cp_set_usingtransmitsas -
684 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
686 struct ieee802_1x_cp_sm *sm = cp_ctx;
687 sm->using_transmit_sa = status;
692 * ieee802_1x_cp_sm_step - Advance EAPOL state machines
693 * @sm: EAPOL state machine
695 * This function is called to advance CP state machines after any change
696 * that could affect their state.
698 void ieee802_1x_cp_sm_step(void *cp_ctx)
701 * Run ieee802_1x_cp_step_run from a registered timeout
702 * to make sure that other possible timeouts/events are processed
703 * and to avoid long function call chains.
705 struct ieee802_1x_cp_sm *sm = cp_ctx;
706 eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
707 eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
711 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
714 struct ieee802_1x_cp_sm *sm = eloop_ctx;
716 ieee802_1x_cp_step_run(sm);
721 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
723 struct ieee802_1x_cp_sm *sm = eloop_ctx;
724 sm->transmit_when = 0;
725 ieee802_1x_cp_step_run(sm);