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;
43 Boolean chgd_server; /* clear by CP */
45 enum confidentiality_offset cipher_offset;
47 Boolean new_sak; /* clear by CP */
48 struct ieee802_1x_mka_ki distributed_ki;
50 Boolean using_receive_sas;
51 Boolean all_receiving;
52 Boolean server_transmitting;
53 Boolean using_transmit_sa;
56 struct ieee802_1x_mka_ki *lki;
60 struct ieee802_1x_mka_ki *oki;
66 Boolean protect_frames;
67 enum validate_frames validate_frames;
69 Boolean replay_protect;
72 u64 current_cipher_suite;
73 enum confidentiality_offset confidentiality_offset;
74 Boolean controlled_port_enabled;
77 Boolean port_enabled; /* SecY->CP */
85 /* not defined IEEE Std 802.1X-2010 */
86 struct ieee802_1x_kay *kay;
89 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
91 static void ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx,
95 static int changed_cipher(struct ieee802_1x_cp_sm *sm)
97 return sm->confidentiality_offset != sm->cipher_offset ||
98 sm->current_cipher_suite != sm->cipher_suite;
102 static int changed_connect(struct ieee802_1x_cp_sm *sm)
104 return sm->connect != SECURE || sm->chgd_server || changed_cipher(sm);
112 sm->controlled_port_enabled = FALSE;
113 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
115 sm->port_valid = FALSE;
127 sm->port_enabled = TRUE;
128 sm->chgd_server = FALSE;
134 SM_ENTRY(CP, CHANGE);
136 sm->port_valid = FALSE;
137 sm->controlled_port_enabled = FALSE;
138 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
141 ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
143 ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
147 SM_STATE(CP, ALLOWED)
149 SM_ENTRY(CP, ALLOWED);
151 sm->protect_frames = FALSE;
152 sm->replay_protect = FALSE;
153 sm->validate_frames = Checked;
155 sm->port_valid = FALSE;
156 sm->controlled_port_enabled = TRUE;
158 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
159 secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
160 secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
161 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
162 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
166 SM_STATE(CP, AUTHENTICATED)
168 SM_ENTRY(CP, AUTHENTICATED);
170 sm->protect_frames = FALSE;
171 sm->replay_protect = FALSE;
172 sm->validate_frames = Checked;
174 sm->port_valid = FALSE;
175 sm->controlled_port_enabled = TRUE;
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);
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_encrypt(sm->kay, sm->kay->macsec_encrypt);
207 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
208 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
212 SM_STATE(CP, RECEIVE)
214 SM_ENTRY(CP, RECEIVE);
215 /* RECEIVE state machine not keep with Figure 12-2 in
216 * IEEE Std 802.1X-2010 */
218 ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
225 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
228 sm->lki = os_malloc(sizeof(*sm->lki));
230 wpa_printf(MSG_ERROR, "CP-%s: Out of memory", __func__);
233 os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki));
234 sm->lan = sm->distributed_an;
237 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
239 ieee802_1x_kay_create_sas(sm->kay, sm->lki);
240 ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki);
242 sm->all_receiving = FALSE;
246 SM_STATE(CP, RECEIVING)
248 SM_ENTRY(CP, RECEIVING);
251 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
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;
270 ieee802_1x_kay_enable_new_info(sm->kay);
274 SM_STATE(CP, TRANSMIT)
276 SM_ENTRY(CP, TRANSMIT);
278 sm->controlled_port_enabled = TRUE;
279 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
281 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
283 ieee802_1x_kay_enable_tx_sas(sm->kay, sm->lki);
284 sm->all_receiving = FALSE;
285 sm->server_transmitting = FALSE;
289 SM_STATE(CP, TRANSMITTING)
291 SM_ENTRY(CP, TRANSMITTING);
292 sm->retire_when = sm->orx ? sm->retire_delay : 0;
294 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
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;
304 SM_STATE(CP, ABANDON)
306 SM_ENTRY(CP, ABANDON);
308 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
310 ieee802_1x_kay_delete_sas(sm->kay, sm->lki);
314 ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan,
322 SM_ENTRY(CP, RETIRE);
323 /* RETIRE state machine not keep with Figure 12-2 in
324 * IEEE Std 802.1X-2010 */
326 ieee802_1x_kay_delete_sas(sm->kay, sm->oki);
332 ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan,
338 * CP state machine handler entry
342 if (!sm->port_enabled)
345 switch (sm->CP_state) {
351 SM_ENTER(CP, CHANGE);
355 if (sm->connect == UNAUTHENTICATED)
356 SM_ENTER(CP, ALLOWED);
357 else if (sm->connect == AUTHENTICATED)
358 SM_ENTER(CP, AUTHENTICATED);
359 else if (sm->connect == SECURE)
360 SM_ENTER(CP, SECURED);
364 if (sm->connect != UNAUTHENTICATED)
365 SM_ENTER(CP, CHANGE);
368 case CP_AUTHENTICATED:
369 if (sm->connect != AUTHENTICATED)
370 SM_ENTER(CP, CHANGE);
374 if (changed_connect(sm))
375 SM_ENTER(CP, CHANGE);
376 else if (sm->new_sak)
377 SM_ENTER(CP, RECEIVE);
381 if (sm->using_receive_sas)
382 SM_ENTER(CP, RECEIVING);
386 if (sm->new_sak || changed_connect(sm))
387 SM_ENTER(CP, ABANDON);
388 if (!sm->elected_self)
390 if (sm->elected_self &&
391 (sm->all_receiving || !sm->controlled_port_enabled ||
393 SM_ENTER(CP, TRANSMIT);
397 if (sm->using_transmit_sa)
398 SM_ENTER(CP, TRANSMITTING);
401 case CP_TRANSMITTING:
402 if (!sm->retire_when || changed_connect(sm))
403 SM_ENTER(CP, RETIRE);
407 if (changed_connect(sm))
408 SM_ENTER(CP, CHANGE);
409 else if (sm->new_sak)
410 SM_ENTER(CP, RECEIVE);
414 if (sm->new_sak || changed_connect(sm))
415 SM_ENTER(CP, ABANDON);
416 if (sm->server_transmitting || !sm->controlled_port_enabled)
417 SM_ENTER(CP, TRANSMIT);
420 if (changed_connect(sm))
421 SM_ENTER(CP, RETIRE);
422 else if (sm->new_sak)
423 SM_ENTER(CP, RECEIVE);
426 wpa_printf(MSG_ERROR, "CP: the state machine is not defined");
433 * ieee802_1x_cp_sm_init -
435 struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
437 struct ieee802_1x_cp_sm *sm;
439 sm = os_zalloc(sizeof(*sm));
441 wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
447 sm->port_valid = FALSE;
449 sm->chgd_server = FALSE;
451 sm->protect_frames = kay->macsec_protect;
452 sm->validate_frames = kay->macsec_validate;
453 sm->replay_protect = kay->macsec_replay_protect;
454 sm->replay_window = kay->macsec_replay_window;
456 sm->controlled_port_enabled = FALSE;
465 sm->current_cipher_suite = default_cs_id;
466 sm->cipher_suite = default_cs_id;
467 sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
468 sm->confidentiality_offset = sm->cipher_offset;
469 sm->transmit_delay = MKA_LIFE_TIME;
470 sm->retire_delay = MKA_SAK_RETIRE_TIME;
471 sm->CP_state = CP_BEGIN;
474 wpa_printf(MSG_DEBUG, "CP: state machine created");
476 secy_cp_control_protect_frames(sm->kay, sm->protect_frames);
477 secy_cp_control_encrypt(sm->kay, sm->kay->macsec_encrypt);
478 secy_cp_control_validate_frames(sm->kay, sm->validate_frames);
479 secy_cp_control_replay(sm->kay, sm->replay_protect, sm->replay_window);
480 secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled);
481 secy_cp_control_confidentiality_offset(sm->kay,
482 sm->confidentiality_offset);
490 static void ieee802_1x_cp_step_run(struct ieee802_1x_cp_sm *sm)
492 enum cp_states prev_state;
495 for (i = 0; i < 100; i++) {
496 prev_state = sm->CP_state;
498 if (prev_state == sm->CP_state)
504 static void ieee802_1x_cp_step_cb(void *eloop_ctx, void *timeout_ctx)
506 struct ieee802_1x_cp_sm *sm = eloop_ctx;
507 ieee802_1x_cp_step_run(sm);
512 * ieee802_1x_cp_sm_deinit -
514 void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm)
516 wpa_printf(MSG_DEBUG, "CP: state machine removed");
520 eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL);
521 eloop_cancel_timeout(ieee802_1x_cp_transmit_when_timeout, sm, NULL);
522 eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
530 * ieee802_1x_cp_connect_pending
532 void ieee802_1x_cp_connect_pending(void *cp_ctx)
534 struct ieee802_1x_cp_sm *sm = cp_ctx;
536 sm->connect = PENDING;
541 * ieee802_1x_cp_connect_unauthenticated
543 void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx)
545 struct ieee802_1x_cp_sm *sm = (struct ieee802_1x_cp_sm *)cp_ctx;
547 sm->connect = UNAUTHENTICATED;
552 * ieee802_1x_cp_connect_authenticated
554 void ieee802_1x_cp_connect_authenticated(void *cp_ctx)
556 struct ieee802_1x_cp_sm *sm = cp_ctx;
558 sm->connect = AUTHENTICATED;
563 * ieee802_1x_cp_connect_secure
565 void ieee802_1x_cp_connect_secure(void *cp_ctx)
567 struct ieee802_1x_cp_sm *sm = cp_ctx;
569 sm->connect = SECURE;
574 * ieee802_1x_cp_set_chgdserver -
576 void ieee802_1x_cp_signal_chgdserver(void *cp_ctx)
578 struct ieee802_1x_cp_sm *sm = cp_ctx;
580 sm->chgd_server = TRUE;
585 * ieee802_1x_cp_set_electedself -
587 void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status)
589 struct ieee802_1x_cp_sm *sm = cp_ctx;
590 sm->elected_self = status;
595 * ieee802_1x_cp_set_ciphersuite -
597 void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
599 struct ieee802_1x_cp_sm *sm = cp_ctx;
600 sm->cipher_suite = cs;
605 * ieee802_1x_cp_set_offset -
607 void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset)
609 struct ieee802_1x_cp_sm *sm = cp_ctx;
610 sm->cipher_offset = offset;
615 * ieee802_1x_cp_signal_newsak -
617 void ieee802_1x_cp_signal_newsak(void *cp_ctx)
619 struct ieee802_1x_cp_sm *sm = cp_ctx;
625 * ieee802_1x_cp_set_distributedki -
627 void ieee802_1x_cp_set_distributedki(void *cp_ctx,
628 const struct ieee802_1x_mka_ki *dki)
630 struct ieee802_1x_cp_sm *sm = cp_ctx;
631 os_memcpy(&sm->distributed_ki, dki, sizeof(struct ieee802_1x_mka_ki));
636 * ieee802_1x_cp_set_distributedan -
638 void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an)
640 struct ieee802_1x_cp_sm *sm = cp_ctx;
641 sm->distributed_an = an;
646 * ieee802_1x_cp_set_usingreceivesas -
648 void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status)
650 struct ieee802_1x_cp_sm *sm = cp_ctx;
651 sm->using_receive_sas = status;
656 * ieee802_1x_cp_set_allreceiving -
658 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status)
660 struct ieee802_1x_cp_sm *sm = cp_ctx;
661 sm->all_receiving = status;
666 * ieee802_1x_cp_set_servertransmitting -
668 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status)
670 struct ieee802_1x_cp_sm *sm = cp_ctx;
671 sm->server_transmitting = status;
676 * ieee802_1x_cp_set_usingtransmitsas -
678 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)
680 struct ieee802_1x_cp_sm *sm = cp_ctx;
681 sm->using_transmit_sa = status;
686 * ieee802_1x_cp_sm_step - Advance EAPOL state machines
687 * @sm: EAPOL state machine
689 * This function is called to advance CP state machines after any change
690 * that could affect their state.
692 void ieee802_1x_cp_sm_step(void *cp_ctx)
695 * Run ieee802_1x_cp_step_run from a registered timeout
696 * to make sure that other possible timeouts/events are processed
697 * and to avoid long function call chains.
699 struct ieee802_1x_cp_sm *sm = cp_ctx;
700 eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
701 eloop_register_timeout(0, 0, ieee802_1x_cp_step_cb, sm, NULL);
705 static void ieee802_1x_cp_retire_when_timeout(void *eloop_ctx,
708 struct ieee802_1x_cp_sm *sm = eloop_ctx;
710 ieee802_1x_cp_step_run(sm);
715 ieee802_1x_cp_transmit_when_timeout(void *eloop_ctx, void *timeout_ctx)
717 struct ieee802_1x_cp_sm *sm = eloop_ctx;
718 sm->transmit_when = 0;
719 ieee802_1x_cp_step_run(sm);