This splits appkey_key_add() into two separate functions: app_key_add() and app_key_update(). Fix checks for miscellaneous invalid conditions and return appropriate error status. --- mesh/appkey.c | 89 +++++++++++++++++++++++++------------------- mesh/appkey.h | 4 +- mesh/cfgmod-server.c | 8 +++- 3 files changed, 60 insertions(+), 41 deletions(-) diff --git a/mesh/appkey.c b/mesh/appkey.c index a437763db..f799b7782 100644 --- a/mesh/appkey.c +++ b/mesh/appkey.c @@ -364,8 +364,8 @@ bool appkey_have_key(struct mesh_net *net, uint16_t app_idx) return true; } -int appkey_key_add(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, - const uint8_t *new_key, bool update) +int appkey_key_update(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, + const uint8_t *new_key) { struct mesh_app_key *key; struct l_queue *app_keys; @@ -375,61 +375,74 @@ int appkey_key_add(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, if (!app_keys) return MESH_STATUS_INSUFF_RESOURCES; - key = l_queue_find(app_keys, match_key_index, L_UINT_TO_PTR(app_idx)); - - if (!mesh_net_have_key(net, net_idx) || - (update && key->net_idx != net_idx)) + if (!mesh_net_have_key(net, net_idx)) return MESH_STATUS_INVALID_NETKEY; - if (update && !key) + key = l_queue_find(app_keys, match_key_index, L_UINT_TO_PTR(app_idx)); + + if (!key) return MESH_STATUS_INVALID_APPKEY; + if (key->net_idx != net_idx) + return MESH_STATUS_INVALID_BINDING; + mesh_net_key_refresh_phase_get(net, net_idx, &phase); - if (update && phase != KEY_REFRESH_PHASE_ONE) + if (phase != KEY_REFRESH_PHASE_ONE) return MESH_STATUS_CANNOT_UPDATE; + /* Check if the key has been already successfully updated */ + if (memcmp(new_key, key->new_key, 16) == 0) + return MESH_STATUS_SUCCESS; + + if (!set_key(key, app_idx, new_key, true)) + return MESH_STATUS_INSUFF_RESOURCES; + + if (!storage_app_key_add(net, net_idx, app_idx, new_key, true)) + return MESH_STATUS_STORAGE_FAIL; + + return MESH_STATUS_SUCCESS; +} + +int appkey_key_add(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, + const uint8_t *new_key) +{ + struct mesh_app_key *key; + struct l_queue *app_keys; + + app_keys = mesh_net_get_app_keys(net); + if (!app_keys) + return MESH_STATUS_INSUFF_RESOURCES; + + key = l_queue_find(app_keys, match_key_index, L_UINT_TO_PTR(app_idx)); if (key) { if (memcmp(new_key, key->key, 16) == 0) return MESH_STATUS_SUCCESS; - - if (!update) { - l_debug("Failed to add key: index already stored %x", - (net_idx << 16) | app_idx); + else return MESH_STATUS_IDX_ALREADY_STORED; - } } - if (!key) { - if (!(l_queue_length(app_keys) < MAX_APP_KEYS)) - return MESH_STATUS_INSUFF_RESOURCES; - - key = app_key_new(); - if (!key) - return MESH_STATUS_INSUFF_RESOURCES; + if (!mesh_net_have_key(net, net_idx)) + return MESH_STATUS_INVALID_NETKEY; - if (!set_key(key, app_idx, new_key, false)) { - appkey_key_free(key); - return MESH_STATUS_INSUFF_RESOURCES; - } + if (l_queue_length(app_keys) >= MAX_APP_KEYS) + return MESH_STATUS_INSUFF_RESOURCES; - if (!storage_app_key_add(net, net_idx, app_idx, new_key, - false)) { - appkey_key_free(key); - return MESH_STATUS_STORAGE_FAIL; - } + key = app_key_new(); - key->net_idx = net_idx; - key->app_idx = app_idx; - l_queue_push_tail(app_keys, key); - } else { - if (!set_key(key, app_idx, new_key, true)) - return MESH_STATUS_INSUFF_RESOURCES; + if (!set_key(key, app_idx, new_key, false)) { + appkey_key_free(key); + return MESH_STATUS_INSUFF_RESOURCES; + } - if (!storage_app_key_add(net, net_idx, app_idx, new_key, - true)) - return MESH_STATUS_STORAGE_FAIL; + if (!storage_app_key_add(net, net_idx, app_idx, new_key, false)) { + appkey_key_free(key); + return MESH_STATUS_STORAGE_FAIL; } + key->net_idx = net_idx; + key->app_idx = app_idx; + l_queue_push_tail(app_keys, key); + l_queue_clear(key->replay_cache, l_free); return MESH_STATUS_SUCCESS; diff --git a/mesh/appkey.h b/mesh/appkey.h index 21bc6a70e..eda82ac3b 100644 --- a/mesh/appkey.h +++ b/mesh/appkey.h @@ -35,7 +35,9 @@ const uint8_t *appkey_get_key(struct mesh_net *net, uint16_t app_idx, uint8_t *key_id); bool appkey_have_key(struct mesh_net *net, uint16_t app_idx); int appkey_key_add(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, - const uint8_t *new_key, bool update); + const uint8_t *new_key); +int appkey_key_update(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx, + const uint8_t *new_key); int appkey_key_delete(struct mesh_net *net, uint16_t net_idx, uint16_t app_idx); void appkey_delete_bound_keys(struct mesh_net *net, uint16_t net_idx); uint8_t appkey_list(struct mesh_net *net, uint16_t net_idx, uint8_t *buf, diff --git a/mesh/cfgmod-server.c b/mesh/cfgmod-server.c index 899bdde2e..992d4ac6a 100644 --- a/mesh/cfgmod-server.c +++ b/mesh/cfgmod-server.c @@ -925,8 +925,12 @@ static bool cfg_srv_pkt(uint16_t src, uint32_t dst, net_idx = l_get_le16(pkt) & 0xfff; app_idx = l_get_le16(pkt + 1) >> 4; - b_res = appkey_key_add(net, net_idx, app_idx, pkt + 3, - opcode == OP_APPKEY_UPDATE); + + if (opcode == OP_APPKEY_ADD) + b_res = appkey_key_add(net, net_idx, app_idx, pkt + 3); + else + b_res = appkey_key_update(net, net_idx, app_idx, + pkt + 3); l_debug("Add/Update AppKey %s: Net_Idx %3.3x, App_Idx %3.3x", (b_res == MESH_STATUS_SUCCESS) ? "success" : "fail", -- 2.17.2