@@ -420,6 +420,43 @@ static uint16_t cfg_relay_msg(struct mesh_node *node, const uint8_t *pkt,
return n;
}
+static uint16_t cfg_key_refresh_phase(struct mesh_node *node,
+ const uint8_t *pkt, int opcode)
+{
+ struct mesh_net *net = node_get_net(node);
+ uint16_t n, idx = l_get_le16(pkt);
+ uint8_t phase;
+ int status;
+
+ n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS, msg);
+ status = mesh_net_key_refresh_phase_get(net, idx, &phase);
+
+ if (status == MESH_STATUS_SUCCESS &&
+ opcode == OP_CONFIG_KEY_REFRESH_PHASE_SET) {
+
+ if (pkt[2] == KEY_REFRESH_TRANS_TWO) {
+ if (phase == KEY_REFRESH_PHASE_TWO)
+ goto done;
+ else if (phase != KEY_REFRESH_PHASE_ONE)
+ return 0;
+ }
+
+ status = mesh_net_key_refresh_phase_set(net, idx, pkt[2]);
+ l_debug("Set KR Phase: net=%3.3x transition=%d", idx, pkt[2]);
+
+ if (status == MESH_STATUS_SUCCESS)
+ mesh_net_key_refresh_phase_get(net, idx, &phase);
+ }
+
+done:
+ msg[n] = status;
+ l_put_le16(idx, msg + n);
+ msg[n + 2] = (status != MESH_STATUS_SUCCESS) ?
+ KEY_REFRESH_PHASE_NONE : phase;
+
+ return n + 3;
+}
+
static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data)
{
struct mesh_net *net = user_data;
@@ -718,8 +755,7 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx,
int b_res = MESH_STATUS_SUCCESS;
struct mesh_net_heartbeat *hb;
uint16_t n_idx;
- uint8_t state, status;
- uint8_t phase;
+ uint8_t state;
bool virt = false;
uint16_t n;
@@ -926,37 +962,17 @@ static bool cfg_srv_pkt(uint16_t src, uint16_t dst, uint16_t app_idx,
break;
case OP_CONFIG_KEY_REFRESH_PHASE_SET:
- if (size != 3 || pkt[2] > 0x03)
+ if (size != 3 || (pkt[2] != KEY_REFRESH_TRANS_THREE &&
+ pkt[2] != KEY_REFRESH_TRANS_TWO))
return true;
- b_res = mesh_net_key_refresh_phase_set(net, l_get_le16(pkt),
- pkt[2]);
- size = 2;
/* Fall Through */
case OP_CONFIG_KEY_REFRESH_PHASE_GET:
- if (size != 2)
+ if (size != 2 && opcode == OP_CONFIG_KEY_REFRESH_PHASE_GET)
return true;
- n_idx = l_get_le16(pkt);
-
- n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS,
- msg);
-
- /* State: 0x00-0x03 phase of key refresh */
- status = mesh_net_key_refresh_phase_get(net, n_idx,
- &phase);
- if (status != MESH_STATUS_SUCCESS) {
- b_res = status;
- phase = KEY_REFRESH_PHASE_NONE;
- }
-
- msg[n++] = b_res;
- l_put_le16(n_idx, msg + n);
- n += 2;
- msg[n++] = phase;
-
- l_debug("Get/Set Key Refresh State (%d)", msg[n-1]);
+ n = cfg_key_refresh_phase(node, pkt, opcode);
break;
case OP_APPKEY_ADD:
@@ -36,6 +36,9 @@
#define KEY_REFRESH_PHASE_TWO 0x02
#define KEY_REFRESH_PHASE_THREE 0x03
+#define KEY_REFRESH_TRANS_TWO 0x02
+#define KEY_REFRESH_TRANS_THREE 0x03
+
#define DEFAULT_TTL 0xff
#define TTL_MASK 0x7f
@@ -2433,6 +2433,10 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
return MESH_STATUS_INVALID_NETKEY;
l_debug("Key refresh procedure phase 2: start using new net TX keys");
+
+ if (subnet->kr_phase == KEY_REFRESH_PHASE_TWO)
+ return MESH_STATUS_SUCCESS;
+
subnet->key_refresh = 1;
subnet->net_key_tx = subnet->net_key_upd;
/*
@@ -2445,8 +2449,9 @@ static int key_refresh_phase_two(struct mesh_net *net, uint16_t idx)
l_queue_foreach(net->friends, frnd_kr_phase2, net);
- mesh_config_net_key_set_phase(node_config_get(net->node), idx,
- KEY_REFRESH_PHASE_TWO);
+ if (!mesh_config_net_key_set_phase(node_config_get(net->node), idx,
+ KEY_REFRESH_PHASE_TWO))
+ return MESH_STATUS_STORAGE_FAIL;
return MESH_STATUS_SUCCESS;
}
@@ -2479,8 +2484,9 @@ static int key_refresh_finish(struct mesh_net *net, uint16_t idx)
l_queue_foreach(net->friends, frnd_kr_phase3, net);
- mesh_config_net_key_set_phase(node_config_get(net->node), idx,
- KEY_REFRESH_PHASE_NONE);
+ if (!mesh_config_net_key_set_phase(node_config_get(net->node), idx,
+ KEY_REFRESH_PHASE_NONE))
+ return MESH_STATUS_STORAGE_FAIL;
return MESH_STATUS_SUCCESS;
}
@@ -3168,45 +3174,22 @@ void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
send_msg_pkt(net, pkt, pkt_len + 1);
}
-uint8_t mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx,
+int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t idx,
uint8_t transition)
{
- struct mesh_subnet *subnet;
-
- if (!net)
- return MESH_STATUS_UNSPECIFIED_ERROR;
-
- subnet = l_queue_find(net->subnets, match_key_index,
- L_UINT_TO_PTR(idx));
- if (!subnet)
- return MESH_STATUS_INVALID_NETKEY;
-
- if (transition == subnet->kr_phase)
- return MESH_STATUS_SUCCESS;
+ switch (transition) {
+ case KEY_REFRESH_TRANS_TWO:
+ return key_refresh_phase_two(net, idx);
- if ((transition != 2 && transition != 3) ||
- transition < subnet->kr_phase)
- return MESH_STATUS_CANNOT_SET;
+ case KEY_REFRESH_TRANS_THREE:
+ return key_refresh_finish(net, idx);
- switch (transition) {
- case 2:
- if (key_refresh_phase_two(net, idx)
- != MESH_STATUS_SUCCESS)
- return MESH_STATUS_CANNOT_SET;
- break;
- case 3:
- if (key_refresh_finish(net, idx)
- != MESH_STATUS_SUCCESS)
- return MESH_STATUS_CANNOT_SET;
- break;
default:
- return MESH_STATUS_CANNOT_SET;
+ return MESH_STATUS_UNSPECIFIED_ERROR;
}
-
- return MESH_STATUS_SUCCESS;
}
-uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t idx,
+int mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t idx,
uint8_t *phase)
{
struct mesh_subnet *subnet;
@@ -320,9 +320,9 @@ void mesh_friend_sub_add(struct mesh_net *net, uint16_t lpn, uint8_t ele_cnt,
const uint8_t *list);
void mesh_friend_sub_del(struct mesh_net *net, uint16_t lpn, uint8_t cnt,
const uint8_t *del_list);
-uint8_t mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t net_idx,
+int mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t net_idx,
uint8_t transition);
-uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t net_idx,
+int mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t net_idx,
uint8_t *phase);
void mesh_net_send_seg(struct mesh_net *net, uint32_t key_id,
uint32_t iv_index, uint8_t ttl, uint32_t seq,