summaryrefslogtreecommitdiff
path: root/cesar/cp
diff options
context:
space:
mode:
authorYacine Belkadi2013-04-03 13:11:05 +0200
committerYacine Belkadi2013-05-23 09:07:13 +0200
commite4b7731e1827efcc1af0a721cb5415039ae6f459 (patch)
tree7fb89129008aaca5551f888a90fb10ad49f7e74c /cesar/cp
parenta5821e5b218bb56400f0ef888a47ad9651484df2 (diff)
cesar/{bsu,cp,mac/pbproc}: change NEK management
Two slots were used to store the NEKs. One for the current NEK, the other for the next NEK. The CP could update any slot at any time, by setting the EKS to MAC_EKS_CLEAR first. One problem is that the pbproc doesn't expect someone to change a key that it is in use. If the cp sets the EKS to MAC_EKS_CLEAR for a key that is in use, may make the pbproc send data unencrypted, which is a problem. Another problem may occur during a NEK change, if the new NEK is not received via the SET_KEY_CNF. In that case, when the countdown starts, the cp sends a GET_KEY_CNF to get the new NEK. When it receives it, it puts the new key in the next slot. To identify the next slot the cp uses bsu_nek_index_next(). This is not reliable around a NEK change: - the cp receives the new NEK - the cp starts setting the new NEK - the cp is suspended - the bsu changes nek_switch - the cp is resumed and calls bsu_nek_index_next() which returns the index of the current NEK instead of the next NEK - the cp writes the new NEK in the current slot instead of the next slot - the pbproc may send packets unencrypted - the NEK change occurs - the new NEK is used in Rx (because the new NEK is in one of the two slots) but not in Tx (because it's not the in the current slot) To fix that, change the way the NEKs are managed: Use pointers and indirection to be able to atomically change a NEK transparently from the pbproc's point of view. Make the cp store the NEKs and set the current NEK, but let the bsu grab the next NEK if it's available.
Diffstat (limited to 'cesar/cp')
-rw-r--r--cesar/cp/av/beacon/test/utest/Makefile1
-rw-r--r--cesar/cp/av/beacon/test/utest/src/beacon.c207
-rw-r--r--cesar/cp/av/beacon/test/utest2/src/beacon_scenario.c27
-rw-r--r--cesar/cp/av/cco/action/src/cco_action.c18
-rw-r--r--cesar/cp/av/cco/action/test/utest/src/assoc.c8
-rw-r--r--cesar/cp/av/cco/action/test/utest2/src/action-test.c21
-rw-r--r--cesar/cp/beacon/beacon.h10
-rw-r--r--cesar/cp/beacon/src/beacon.c109
-rw-r--r--cesar/cp/src/cp.c1
9 files changed, 300 insertions, 102 deletions
diff --git a/cesar/cp/av/beacon/test/utest/Makefile b/cesar/cp/av/beacon/test/utest/Makefile
index 95f9b2f738..fc60d27d61 100644
--- a/cesar/cp/av/beacon/test/utest/Makefile
+++ b/cesar/cp/av/beacon/test/utest/Makefile
@@ -1,4 +1,5 @@
BASE = ../../../../..
+DEFS = -DNO_PRIVATE
INCLUDES = cp/av/beacon/test/utest/override
ECOS = y
diff --git a/cesar/cp/av/beacon/test/utest/src/beacon.c b/cesar/cp/av/beacon/test/utest/src/beacon.c
index ce9d6f8b23..52dc71f3da 100644
--- a/cesar/cp/av/beacon/test/utest/src/beacon.c
+++ b/cesar/cp/av/beacon/test/utest/src/beacon.c
@@ -42,6 +42,10 @@ cp_beacon_receive (cp_t *ctx, bsu_beacon_t *beacon);
void
cp_beacon_sta_compute_schedules (cp_t *ctx, bsu_beacon_t *beacon_data);
+extern mac_nek_t *
+cp_beacon_store_nek (mac_nek_mgr_t *nek_mgr, u8 eks, const u32 *nek_enc,
+ const u32 *nek_dec);
+
struct test_beacon_t
{
cp_t cp;
@@ -589,11 +593,6 @@ test_case_beacon_eks_change_sta (test_t test)
beacon->bmis.eks.kccd = 2;
beacon->bmis.eks.kbc = BSU_BEACON_EKS_KBC_NEK;
beacon->bmis.eks.new_eks = MAC_EKS_MIN + 1;
- mac_eks_t ref_eks_current = MAC_EKS_MIN + 2;
- mac_eks_t ref_eks_next = MAC_EKS_MIN + 3;
- ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks =
- ref_eks_current;
- ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = ref_eks_next;
/** Check default values. */
test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
@@ -604,11 +603,6 @@ test_case_beacon_eks_change_sta (test_t test)
test_fail_unless (ctx.cp.beacon.eks.kccd == 2);
test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
- test_fail_unless (
- ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
- ref_eks_current);
- test_fail_unless (ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
- ref_eks_next);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.eks.present = true;
@@ -621,11 +615,6 @@ test_case_beacon_eks_change_sta (test_t test)
test_fail_unless (ctx.cp.beacon.eks.kccd == 1);
test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK);
test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
- test_fail_unless (
- ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
- ref_eks_current);
- test_fail_unless (ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks ==
- ref_eks_next);
/* Create the beacon. */
beacon = test_new_beacon ();
beacon->bmis.eks.present = false;
@@ -634,11 +623,6 @@ test_case_beacon_eks_change_sta (test_t test)
cp_beacon_receive (&ctx.cp, beacon);
cp_beacon_get_and_process_beacon (&ctx.cp);
test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
- test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
- test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
- test_fail_unless (
- ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks ==
- ref_eks_current);
dbg_check (mac_store_sta_remove (ctx.cp.mac_store, 1));
test_beacon_uninit (&ctx);
}
@@ -703,14 +687,192 @@ test_case_beacon_eks_change_sta (test_t test)
cp_beacon_get_and_process_beacon (&ctx.cp);
test_fail_unless (ctx.cp.beacon.eks.kccd == 0);
- test_fail_unless (ctx.cp.beacon.eks.kbc == BSU_BEACON_EKS_KBC_NB);
- test_fail_unless (ctx.cp.beacon.eks.new_eks == MAC_EKS_MIN + 1);
test_beacon_uninit (&ctx);
}
test_end;
}
+/**
+ * Check whether two NEKs are identical.
+ * \param nek1 One NEK.
+ * \param nek2 Another NEK.
+ * \return true if the two NEKs are identical. false otherwise.
+ */
+static int
+nek_equal (const mac_nek_t *nek1, const mac_nek_t *nek2)
+{
+ dbg_assert (nek1);
+ dbg_assert (nek2);
+ if ((nek1->eks != nek2->eks)
+ || (nek1->in_use != nek2->in_use))
+ return false;
+ uint i;
+ for (i = 0; i < COUNT (nek1->nek_enc); i++)
+ if ((nek1->nek_enc[i] != nek2->nek_enc[i])
+ || (nek1->nek_dec[i] != nek2->nek_dec[i]))
+ return false;
+
+ return true;
+}
+
+void
+test_case_beacon_store_nek (test_t test)
+{
+ test_case_begin (test, "Store NEK");
+ test_begin (test, "Assumptions")
+ {
+ /* Test written with the assumption that: */
+ test_fail_unless (MAC_NEK_STORE_NB == 4);
+ }
+ test_end;
+ test_begin (test, "First store")
+ {
+ mac_nek_t nek0 = {
+ .eks = MAC_EKS_NB,
+ .in_use = false,
+ .nek_enc = { 0xe71e99fd, 0xea5685c4, 0x824499de, 0xd0d1fb8a },
+ .nek_dec = { 0xff723b6a, 0xd91d59c5, 0xb5a7198b, 0x90d40a5c }
+ };
+ mac_nek_t nek1 = {
+ .eks = MAC_EKS_NB,
+ .in_use = false,
+ .nek_enc = { 0xa5e4977d, 0x99d1df2d, 0x9227c17a, 0xbe35c331 },
+ .nek_dec = { 0xf47dc19b, 0x9f0207f4, 0xb40b43f1, 0x9ddef6aa }
+ };
+ mac_nek_t nek2 = {
+ .eks = MAC_EKS_NB,
+ .in_use = false,
+ .nek_enc = { 0xccc91b46, 0xc3021795, 0x8f1be4ef, 0xcac5f9bf },
+ .nek_dec = { 0xa37bab59, 0xc447b12a, 0xe439c42c, 0x9459abcf }
+ };
+ mac_nek_t nek3 = {
+ .eks = MAC_EKS_NB,
+ .in_use = false,
+ .nek_enc = { 0x8723c3e0, 0x96a17af7, 0xf846237e, 0xc3a15eaa },
+ .nek_dec = { 0x907d30ab, 0x8ae981ab, 0xc424838d, 0x9c390970 }
+ };
+ mac_nek_mgr_t nek_mgr = {
+ .use = { NULL, NULL },
+ .next_nek = NULL,
+ .store = { nek0, nek1, nek2, nek3 }
+ };
+ mac_nek_t new_nek = {
+ .eks = 2,
+ .in_use = false,
+ .nek_enc = { 0xfe229a94, 0x97149ba2, 0xc0a6783c, 0xc86a0eca },
+ .nek_dec = { 0x9f878bc9, 0xd588a32f, 0x843e3367, 0xbe07b978 }
+ };
+
+ mac_nek_t *ret = cp_beacon_store_nek (&nek_mgr, new_nek.eks,
+ new_nek.nek_enc, new_nek.nek_dec);
+
+ test_fail_unless (ret == &nek_mgr.store[0]);
+ test_fail_unless (nek_equal (&nek_mgr.store[0], &new_nek));
+ test_fail_unless (nek_equal (&nek_mgr.store[1], &nek1));
+ test_fail_unless (nek_equal (&nek_mgr.store[2], &nek2));
+ test_fail_unless (nek_equal (&nek_mgr.store[3], &nek3));
+ }
+ test_end;
+ test_begin (test, "Store:Preserve next_nek")
+ {
+ mac_nek_t nek0 = {
+ .eks = 1,
+ .in_use = true,
+ .nek_enc = { 0xe71e99fd, 0xea5685c4, 0x824499de, 0xd0d1fb8a },
+ .nek_dec = { 0xff723b6a, 0xd91d59c5, 0xb5a7198b, 0x90d40a5c }
+ };
+ mac_nek_t nek1 = {
+ .eks = 2,
+ .in_use = true,
+ .nek_enc = { 0xa5e4977d, 0x99d1df2d, 0x9227c17a, 0xbe35c331 },
+ .nek_dec = { 0xf47dc19b, 0x9f0207f4, 0xb40b43f1, 0x9ddef6aa }
+ };
+ mac_nek_t nek2 = {
+ .eks = 5,
+ .in_use = false,
+ .nek_enc = { 0xccc91b46, 0xc3021795, 0x8f1be4ef, 0xcac5f9bf },
+ .nek_dec = { 0xa37bab59, 0xc447b12a, 0xe439c42c, 0x9459abcf }
+ };
+ mac_nek_t nek3 = {
+ .eks = 6,
+ .in_use = false,
+ .nek_enc = { 0x8723c3e0, 0x96a17af7, 0xf846237e, 0xc3a15eaa },
+ .nek_dec = { 0x907d30ab, 0x8ae981ab, 0xc424838d, 0x9c390970 }
+ };
+ mac_nek_mgr_t nek_mgr = {
+ .use = { NULL, NULL },
+ .store = { nek0, nek1, nek2, nek3 }
+ };
+ nek_mgr.next_nek = &nek_mgr.store[2];
+
+ mac_nek_t new_nek = {
+ .eks = 2,
+ .in_use = false,
+ .nek_enc = { 0xfe229a94, 0x97149ba2, 0xc0a6783c, 0xc86a0eca },
+ .nek_dec = { 0x9f878bc9, 0xd588a32f, 0x843e3367, 0xbe07b978 }
+ };
+
+ mac_nek_t *ret = cp_beacon_store_nek (&nek_mgr, new_nek.eks,
+ new_nek.nek_enc, new_nek.nek_dec);
+
+ test_fail_unless (ret == &nek_mgr.store[3]);
+ test_fail_unless (nek_equal (&nek_mgr.store[0], &nek0));
+ test_fail_unless (nek_equal (&nek_mgr.store[1], &nek1));
+ test_fail_unless (nek_equal (&nek_mgr.store[2], &nek2));
+ test_fail_unless (nek_equal (&nek_mgr.store[3], &new_nek));
+ }
+ test_end;
+ test_begin (test, "Store:Full")
+ {
+ mac_nek_t nek0 = {
+ .eks = 2,
+ .in_use = true,
+ .nek_enc = { 0xe71e99fd, 0xea5685c4, 0x824499de, 0xd0d1fb8a },
+ .nek_dec = { 0xff723b6a, 0xd91d59c5, 0xb5a7198b, 0x90d40a5c }
+ };
+ mac_nek_t nek1 = {
+ .eks = 7,
+ .in_use = false,
+ .nek_enc = { 0xa5e4977d, 0x99d1df2d, 0x9227c17a, 0xbe35c331 },
+ .nek_dec = { 0xf47dc19b, 0x9f0207f4, 0xb40b43f1, 0x9ddef6aa }
+ };
+ mac_nek_t nek2 = {
+ .eks = 1,
+ .in_use = true,
+ .nek_enc = { 0xccc91b46, 0xc3021795, 0x8f1be4ef, 0xcac5f9bf },
+ .nek_dec = { 0xa37bab59, 0xc447b12a, 0xe439c42c, 0x9459abcf }
+ };
+ mac_nek_t nek3 = {
+ .eks = 4,
+ .in_use = true,
+ .nek_enc = { 0x8723c3e0, 0x96a17af7, 0xf846237e, 0xc3a15eaa },
+ .nek_dec = { 0x907d30ab, 0x8ae981ab, 0xc424838d, 0x9c390970 }
+ };
+ mac_nek_mgr_t nek_mgr = {
+ .use = { NULL, NULL },
+ .store = { nek0, nek1, nek2, nek3 }
+ };
+ nek_mgr.next_nek = &nek_mgr.store[1];
+ mac_nek_t new_nek = {
+ .eks = 2,
+ .in_use = false,
+ .nek_enc = { 0xfe229a94, 0x97149ba2, 0xc0a6783c, 0xc86a0eca },
+ .nek_dec = { 0x9f878bc9, 0xd588a32f, 0x843e3367, 0xbe07b978 }
+ };
+
+ mac_nek_t *ret = cp_beacon_store_nek (&nek_mgr, new_nek.eks,
+ new_nek.nek_enc, new_nek.nek_dec);
+
+ test_fail_unless (ret == NULL);
+ test_fail_unless (nek_equal (&nek_mgr.store[0], &nek0));
+ test_fail_unless (nek_equal (&nek_mgr.store[1], &nek1));
+ test_fail_unless (nek_equal (&nek_mgr.store[2], &nek2));
+ test_fail_unless (nek_equal (&nek_mgr.store[3], &nek3));
+ }
+ test_end;
+}
+
void
test_suite_beacon_eks_change (test_t test)
{
@@ -718,6 +880,7 @@ test_suite_beacon_eks_change (test_t test)
test_case_beacon_eks_change_cco (test);
test_case_beacon_eks_change_sta (test);
+ test_case_beacon_store_nek (test);
}
void
diff --git a/cesar/cp/av/beacon/test/utest2/src/beacon_scenario.c b/cesar/cp/av/beacon/test/utest2/src/beacon_scenario.c
index 87f3d27571..64877656a7 100644
--- a/cesar/cp/av/beacon/test/utest2/src/beacon_scenario.c
+++ b/cesar/cp/av/beacon/test/utest2/src/beacon_scenario.c
@@ -42,12 +42,6 @@ beacon_same_nid_test_case (test_t test)
/* This device is cco */
cco_status = true;
- mac_eks_t ref_eks_current = MAC_EKS_MIN + 2;
- mac_eks_t ref_eks_next = MAC_EKS_MIN + 3;
-
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks = ref_eks_current;
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = ref_eks_next;
-
test_case_begin (test, "get_and_process_beacon");
beacon = (bsu_beacon_t *) blk_alloc ();
@@ -121,8 +115,9 @@ beacon_nek_request_test_case (test_t test)
mac_eks_t ref_eks_current = MAC_EKS_MIN + 2;
mac_eks_t ref_eks_next = MAC_EKS_MIN + 3;
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks = ref_eks_current;
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = ref_eks_next;
+ mac_config.nek_mgr.store[0].eks = ref_eks_current;
+ mac_config.nek_mgr.store[1].eks = ref_eks_next;
+ mac_config.nek_mgr.next_nek = &mac_config.nek_mgr.store[1];
test_case_begin (test, "get_and_process_beacon");
@@ -202,6 +197,8 @@ beacon_nek_request_test_case (test_t test)
/* Test with everything ok, but the local next eks is invalid
* we check that a nek_request event is sent. */
+ mac_config.nek_mgr.next_nek = NULL;
+
beacon = (bsu_beacon_t *) blk_alloc ();
beacon->bmis.eks.present = true;
beacon->bmis.eks.kbc = BSU_BEACON_EKS_KBC_NEK;
@@ -213,7 +210,6 @@ beacon_nek_request_test_case (test_t test)
beacon->bmis.mac_address.present = false;
beacon->params.direction = BSU_BEACON_DIRECTION_FROM_PLC;
cp_beacon_receive (&cp, beacon);
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = MAC_EKS_CLEAR;
test_begin (test, "next eks is invalid")
{
scenario_entry_t entries[] =
@@ -234,13 +230,7 @@ beacon_nek_request_test_case (test_t test)
beacon->bmis.eks.present = false;
beacon->params.rx_parameters.snid = 1;
beacon->bmis.mac_address.present = false;
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks =
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks;
- mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks = MAC_EKS_CLEAR;
-
beacon->params.direction = BSU_BEACON_DIRECTION_FROM_PLC;
- cp.beacon.last_countdown_call_date = phy_date () -
- BSU_ACLF_50HZ_CLK_MAX_TCK;
cp_beacon_receive (&cp, beacon);
test_begin (test, "next eks is invalid")
{
@@ -248,7 +238,7 @@ beacon_nek_request_test_case (test_t test)
{
SCENARIO_ACTION (get_and_process_beacon),
SCENARIO_EVENT (cp_fsm_event_bare_new,
- .type =CP_FSM_EVENT_TYPE_to_leave),
+ .type =CP_FSM_EVENT_TYPE_to_leave),
SCENARIO_END
};
scenario_run (test, entries, &globals);
@@ -256,8 +246,9 @@ beacon_nek_request_test_case (test_t test)
test_end;
/* Test the countdown elapsed and a nek was received */
- mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = MAC_EKS_MIN;
cp.beacon.eks.kccd = 1;
+ cp.beacon.eks.new_eks = 5; /* Must match the EKS of the NEK returned by the
+ stub version of bsu_nek_get_current () */
beacon = (bsu_beacon_t *) blk_alloc ();
beacon->vf.stei = 1;
beacon->vf.nid = 1;
@@ -267,7 +258,7 @@ beacon_nek_request_test_case (test_t test)
beacon->params.direction = BSU_BEACON_DIRECTION_FROM_PLC;
cp_beacon_receive (&cp, beacon);
- test_begin (test, "next eks is invalid")
+ test_begin (test, "next eks is valid")
{
scenario_entry_t entries[] =
{
diff --git a/cesar/cp/av/cco/action/src/cco_action.c b/cesar/cp/av/cco/action/src/cco_action.c
index d99e65bc27..d9152cab07 100644
--- a/cesar/cp/av/cco/action/src/cco_action.c
+++ b/cesar/cp/av/cco/action/src/cco_action.c
@@ -914,11 +914,10 @@ cp_av_cco_action_cco__cm_get_key_req_pid0 (cp_t *ctx, cp_mme_rx_t * get_key_req)
if (req.key_type == CP_MSG_KEY_NEK)
{
uint i;
- uint index = bsu_nek_index_current (ctx->bsu);
- cnf.eks = ctx->mac_config->nek[index].eks;
- for (i = 0; i < COUNT (ctx->mac_config->nek[0].nek_enc); i++)
- cnf.key.key[i] =
- ctx->mac_config->nek[index].nek_enc[i];
+ mac_nek_t *nek = bsu_nek_get_current (ctx->bsu);
+ cnf.eks = nek->eks;
+ for (i = 0; i < COUNT (nek->nek_enc); i++)
+ cnf.key.key[i] = nek->nek_enc[i];
}
/* Send the TEI map. */
@@ -968,11 +967,10 @@ cp_av_cco_action_cco__cm_get_key_req_pid1 (cp_t *ctx, cp_mme_rx_t * get_key_req)
cnf.result = CP_MSG_CM_GET_KEY_CNF_RESULT_KEY_GRANTED;
uint i;
- uint index = bsu_nek_index_next (ctx->bsu);
- cnf.eks = ctx->mac_config->nek[index].eks;
- for (i = 0; i < COUNT (ctx->mac_config->nek[0].nek_enc); i++)
- cnf.key.key[i] =
- ctx->mac_config->nek[index].nek_enc[i];
+ cnf.eks = ctx->cco_action.new_nek.eks;
+ cp_key_t *key = &ctx->cco_action.new_nek.nek_enc;
+ for (i = 0; i < COUNT (key->key); i++)
+ cnf.key.key[i] = key->key[i];
}
else
cnf.result =
diff --git a/cesar/cp/av/cco/action/test/utest/src/assoc.c b/cesar/cp/av/cco/action/test/utest/src/assoc.c
index 1c3bd74a23..63278fb346 100644
--- a/cesar/cp/av/cco/action/test/utest/src/assoc.c
+++ b/cesar/cp/av/cco/action/test/utest/src/assoc.c
@@ -115,8 +115,8 @@ assoc_test_case_cco (test_t t)
MAC_NM_CSMA_ONLY);
slab_release (sta);
/* Receive an Get key request from the associated STA. */
- mac_eks_t eks = MAC_EKS_MIN + 1;
- ctx.mac_config.nek[bsu_nek_index_current (INVALID_PTR)].eks = eks;
+ mac_eks_t eks = 5; /* Must be the same as the one returned by the bsu
+ stub version of bsu_nek_get_current() */
scenario_entry_t auth [] = {
/* Refuse access - wrong TEI. */
SCENARIO_ACTION (cco__cm_get_key_req_pid0,
@@ -305,8 +305,8 @@ assoc_test_case_nek_request (test_t t)
cp_sta_set_authenticated (&ctx.cp, sta, true);
cp_mme_peer_t peer = CP_MME_PEER (sta_mac, sta_tei);
- mac_eks_t eks = MAC_EKS_MIN + 1;
- ctx.mac_config.nek[bsu_nek_index_next (INVALID_PTR)].eks = eks;
+ mac_eks_t eks = 4;
+ ctx.cp.cco_action.new_nek.eks = eks;
test_case_begin (t, "CCO receive a nek request");
test_begin (t, "request ok")
diff --git a/cesar/cp/av/cco/action/test/utest2/src/action-test.c b/cesar/cp/av/cco/action/test/utest2/src/action-test.c
index 81fae9a780..0e3c3c5191 100644
--- a/cesar/cp/av/cco/action/test/utest2/src/action-test.c
+++ b/cesar/cp/av/cco/action/test/utest2/src/action-test.c
@@ -318,7 +318,7 @@ test_case_cco_action_start (test_t test)
!= cp_sta_own_data_get_snid (&cp));
test_fail_unless (cp_sta_own_data_get_cco_status (&cp));
test_fail_unless (MAC_TEI_IS_STA (cp_sta_own_data_get_tei (&cp)));
- test_fail_if (cp.mac_config->nek[0].nek_enc[0] == 0);
+ test_fail_if (cp.mac_config->nek_mgr.use[0]->nek_enc[0] == 0);
}
test_end;
@@ -1373,14 +1373,15 @@ cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek, bool now)
{
dbg_assert (ctx);
- ctx->mac_config->nek[0].eks = MAC_EKS_MAX - 1;
- ctx->mac_config->nek[0].nek_enc[0] = nek.key[0];
- ctx->mac_config->nek[0].nek_enc[1] = nek.key[1];
- ctx->mac_config->nek[0].nek_enc[2] = nek.key[2];
- ctx->mac_config->nek[0].nek_enc[3] = nek.key[3];
- ctx->mac_config->nek[0].nek_dec[0] = nek.key[3];
- ctx->mac_config->nek[0].nek_dec[1] = nek.key[2];
- ctx->mac_config->nek[0].nek_dec[2] = nek.key[1];
- ctx->mac_config->nek[0].nek_dec[3] = nek.key[0];
+ ctx->mac_config->nek_mgr.store[0].eks = MAC_EKS_MAX - 1;
+ ctx->mac_config->nek_mgr.store[0].nek_enc[0] = nek.key[0];
+ ctx->mac_config->nek_mgr.store[0].nek_enc[1] = nek.key[1];
+ ctx->mac_config->nek_mgr.store[0].nek_enc[2] = nek.key[2];
+ ctx->mac_config->nek_mgr.store[0].nek_enc[3] = nek.key[3];
+ ctx->mac_config->nek_mgr.store[0].nek_dec[0] = nek.key[3];
+ ctx->mac_config->nek_mgr.store[0].nek_dec[1] = nek.key[2];
+ ctx->mac_config->nek_mgr.store[0].nek_dec[2] = nek.key[1];
+ ctx->mac_config->nek_mgr.store[0].nek_dec[3] = nek.key[0];
+ ctx->mac_config->nek_mgr.use[0] = &ctx->mac_config->nek_mgr.store[0];
}
diff --git a/cesar/cp/beacon/beacon.h b/cesar/cp/beacon/beacon.h
index f621248037..7c765e78e6 100644
--- a/cesar/cp/beacon/beacon.h
+++ b/cesar/cp/beacon/beacon.h
@@ -108,12 +108,12 @@ void
cp_beacon_beacon_not_received (cp_t *ctx);
/**
- * Set the nek in the beacon module.
+ * Change the NEK.
* \param ctx the CP context.
- * \param eks the eks tu use.
- * \param nek the nek key.
- * \param now indicate if the nek shall be use right now.
- */
+ * \param eks the EKS of the NEK.
+ * \param nek the encryption part of the NEK.
+ * \param now True, to use the NEK now (i.e. as the current NEK).
+ * False, to use it as the next NEK. */
void
cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek, bool now);
diff --git a/cesar/cp/beacon/src/beacon.c b/cesar/cp/beacon/src/beacon.c
index f1385de89a..086253b8e1 100644
--- a/cesar/cp/beacon/src/beacon.c
+++ b/cesar/cp/beacon/src/beacon.c
@@ -570,12 +570,15 @@ cp_beacon_process_bmi_eks (cp_t *ctx, const bsu_beacon_t *beacon)
if (beacon->bmis.eks.present)
{
- if ((beacon->bmis.eks.kbc == BSU_BEACON_EKS_KBC_NEK)
- && (ctx->mac_config->nek[bsu_nek_index_next (ctx->bsu)].eks
- != beacon->bmis.eks.new_eks))
+ if ((beacon->bmis.eks.kbc == BSU_BEACON_EKS_KBC_NEK))
{
- /* We don't have the new NEK. We need to ask for it. */
- cp_fsm_post_new_event (ctx, bare, nek_request);
+ if ((ctx->mac_config->nek_mgr.next_nek == NULL)
+ || (ctx->mac_config->nek_mgr.next_nek->eks
+ != beacon->bmis.eks.new_eks))
+ {
+ /* We don't have the new NEK. We need to ask for it. */
+ cp_fsm_post_new_event (ctx, bare, nek_request);
+ }
}
ctx->beacon.eks.kccd = beacon->bmis.eks.kccd;
@@ -588,12 +591,13 @@ cp_beacon_process_bmi_eks (cp_t *ctx, const bsu_beacon_t *beacon)
{
if (ctx->beacon.eks.kbc == BSU_BEACON_EKS_KBC_NEK)
{
- if (ctx->mac_config->nek[
- bsu_nek_index_current (ctx->bsu)].eks == MAC_EKS_CLEAR)
- /* Countdown elapsed and no NEK is available */
+ mac_nek_t *nek = bsu_nek_get_current (ctx->bsu);
+ if (nek->eks != ctx->beacon.eks.new_eks)
+ {
+ /* The countdown elapsed and we are not using the new NEK.
+ */
cp_fsm_trigger_new_event (ctx, bare, to_leave);
-
- ctx->beacon.eks.kbc = BSU_BEACON_EKS_KBC_NB;
+ }
}
}
ctx->beacon.eks.kccd = 0;
@@ -708,7 +712,6 @@ cp_beacon_process_beacon_central (
beacon->bmis.handover.hcd;
ctx->beacon.hoip.cco = beacon->bmis.handover.tei;
}
-
cp_beacon_process_bmi_eks (ctx, beacon);
/** Update the schedules. */
@@ -905,25 +908,78 @@ cp_beacon_beacon_not_received (cp_t *ctx)
}
/**
- * Set the nek in the beacon module.
- * \param ctx the CP context.
- * \param eks the eks tu use.
- * \param nek the nek key.
- * \param now indicate if the nek shall be use right now.
+ * Store a NEK.
+ * \param nek_mgr the NEK management structure.
+ * \param eks The eks of the NEK to store.
+ * \param nek_enc The encryption part of the NEK to store.
+ * \param nek_dec The decryption part of the NEK to store.
+ * \return A pointer to the stored NEK, or NULL if the storage failed.
*/
+PRIVATE mac_nek_t *
+cp_beacon_store_nek (mac_nek_mgr_t *nek_mgr, u8 eks, const u32 *nek_enc,
+ const u32 *nek_dec)
+{
+ /* Find a free slot. i.e. A slot that is neither in use, nor containing the
+ * next key. */
+ /* arch_dsr_lock() is not necessary for the search, because even if this
+ * function is interrupted, a free slot will remain free, because only the
+ * cp fills slots, and this function is called by the cp, and the cp doesn't
+ * interrupt the cp.
+ * */
+ mac_nek_t *nek = NULL;
+ uint i;
+ for (i = 0; i < MAC_NEK_STORE_NB; i++)
+ {
+ if ((nek_mgr->store[i].in_use == false)
+ && (&nek_mgr->store[i] != nek_mgr->next_nek))
+ {
+ nek = &nek_mgr->store[i];
+ break;
+ }
+ }
+
+ if (nek == NULL)
+ return NULL;
+
+ /* Put the key in the free slot. */
+ nek->eks = eks;
+ for (i = 0; i < COUNT (nek->nek_enc); i++)
+ {
+ nek->nek_enc[i] = nek_enc[i];
+ nek->nek_dec[i] = nek_dec[i];
+ }
+
+ /* Ensure the storage of the NEK is over, before returning.
+ * Probably not necessary before returning from a function, but seems safer
+ * in case this is inlined, for example (?) */
+ arch_reorder_barrier ();
+
+ return nek;
+}
+
void
-cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek, bool now)
+cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek_enc, bool now)
{
- cp_key_t rnek;
- uint i,index;
+ cp_key_t nek_dec;
dbg_assert (ctx);
dbg_assert (ctx->mac_config);
+ cp_secu_pbb_dec_gen (nek_enc, &nek_dec);
+
+ mac_nek_t *nek = cp_beacon_store_nek (&ctx->mac_config->nek_mgr, eks,
+ nek_enc.key, nek_dec.key);
+
+ /* Failing to store the NEK should not happen (See MAC_NEK_STORE_NB). */
+ dbg_assert (nek);
+
if (now)
- index = bsu_nek_index_current (ctx->bsu);
+ {
+ bsu_nek_use (ctx->bsu, nek);
+ }
else
{
- index = bsu_nek_index_next (ctx->bsu);
+ bsu_nek_set_next (ctx->bsu, nek);
+
if (cp_sta_own_data_get_cco_status (ctx))
{
/* Initiate key change countdown. */
@@ -932,17 +988,6 @@ cp_beacon_change_nek (cp_t *ctx, uint eks, cp_key_t nek, bool now)
ctx->beacon.eks.new_eks = eks;
}
}
-
- cp_secu_pbb_dec_gen (nek, &rnek);
- ctx->mac_config->nek[index].eks = MAC_EKS_CLEAR;
- arch_reorder_barrier ();
- for (i = 0; i < COUNT(nek.key); i++)
- {
- ctx->mac_config->nek[index].nek_enc[i] = nek.key[i];
- ctx->mac_config->nek[index].nek_dec[i] = rnek.key[i];
- }
- arch_reorder_barrier ();
- ctx->mac_config->nek[index].eks = eks;
}
/**
diff --git a/cesar/cp/src/cp.c b/cesar/cp/src/cp.c
index 45c001d716..f73a023866 100644
--- a/cesar/cp/src/cp.c
+++ b/cesar/cp/src/cp.c
@@ -158,4 +158,3 @@ cp_compute_nmk_and_nid_from_npw (cp_t *ctx, const char *npw,
cp_sta_own_data_set_nmk (ctx, nmk,
CP_MSG_DRV_STA_SET_KEY_TYPE_CHANGE_NID);
}
-