Files
esp-matter/components/esp_matter_controller/esp_matter_controller_group_settings.cpp
T
WanqQixiang 0890dbc8d9 controller: Add groupsettings command
controller: Add invoking commands and writing attributes commands for group_key_management cluster

controller: Add invoking commands for groups cluster
2023-02-23 15:52:42 +08:00

230 lines
9.3 KiB
C++

// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <esp_check.h>
#include <esp_matter_commissioner.h>
#include <esp_matter_controller_group_settings.h>
#include <esp_matter_controller_utils.h>
using chip::FabricIndex;
using chip::KeysetId;
using chip::Credentials::GroupDataProvider;
constexpr char TAG[] = "groupsettings";
namespace esp_matter {
namespace controller {
namespace group_settings {
static bool find_keyset_id(FabricIndex fabric_index, uint16_t group_id, KeysetId &keyset_id)
{
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
GroupDataProvider::GroupKey group_key;
while (iter->Next(group_key)) {
if (group_key.group_id == group_id) {
keyset_id = group_key.keyset_id;
iter->Release();
return true;
}
}
iter->Release();
return false;
}
esp_err_t show_groups()
{
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
ESP_LOGI(TAG, " | Available Groups : |");
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
ESP_LOGI(TAG, " | Group Id | KeySet Id | Group Name |");
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
auto iter = group_data_provider->IterateGroupInfo(fabric_index);
GroupDataProvider::GroupInfo group_info;
if (iter) {
while (iter->Next(group_info)) {
chip::KeysetId keyset_id;
if (find_keyset_id(fabric_index, group_info.group_id, keyset_id)) {
ESP_LOGI(TAG, " | 0x%-12x 0x%-13x %-50s |", group_info.group_id, keyset_id, group_info.name);
} else {
ESP_LOGI(TAG, " | 0x%-12x %-15s %-50s |", group_info.group_id, "None", group_info.name);
}
}
iter->Release();
}
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
return ESP_OK;
}
esp_err_t add_group(char *group_name, uint16_t group_id)
{
if (strlen(group_name) > CHIP_CONFIG_MAX_GROUP_NAME_LENGTH || group_id == chip::kUndefinedGroupId) {
return ESP_ERR_INVALID_ARG;
}
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
GroupDataProvider::GroupInfo group_info;
group_info.SetName(group_name);
group_info.group_id = group_id;
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->SetGroupInfo(fabric_index, group_info), ESP_FAIL, TAG,
"Failed to set the group info");
return ESP_OK;
}
esp_err_t remove_group(uint16_t group_id)
{
if (group_id == chip::kUndefinedGroupId) {
return ESP_ERR_INVALID_ARG;
}
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveGroupInfo(fabric_index, group_id), ESP_FAIL, TAG,
"Failed to remove the group info");
return ESP_OK;
}
esp_err_t show_keysets()
{
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
GroupDataProvider::KeySet keyset;
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
ESP_LOGI(TAG, " | Available KeySets : |");
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
ESP_LOGI(TAG, " | KeySet Id | Key Policy |");
auto iter = group_data_provider->IterateKeySets(fabric_index);
if (iter) {
while (iter->Next(keyset)) {
ESP_LOGI(TAG, " | 0x%-12x %-66s |", keyset.keyset_id,
(keyset.policy == GroupDataProvider::SecurityPolicy::kCacheAndSync) ? "Cache and Sync"
: "Trust First");
}
iter->Release();
}
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
return ESP_OK;
}
esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id)
{
size_t current_count = 0;
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
current_count = iter->Count();
iter->Release();
if (CHIP_NO_ERROR !=
group_data_provider->SetGroupKeyAt(fabric_index, current_count,
GroupDataProvider::GroupKey(group_id, keyset_id))) {
ESP_LOGE(TAG, "Failed to bind keyset");
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id)
{
size_t index = 0;
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
size_t max_count = iter->Count();
GroupDataProvider::GroupKey group_key;
while (iter->Next(group_key)) {
if (group_key.group_id == group_id && group_key.keyset_id == keyset_id) {
break;
}
index++;
}
iter->Release();
ESP_RETURN_ON_FALSE(index < max_count, ESP_ERR_NOT_FOUND, TAG, "Failed to find the group key");
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveGroupKeyAt(fabric_index, index), ESP_FAIL, TAG,
"Failed to remove the group key");
return ESP_OK;
}
esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_time, char *epoch_key_oct_str)
{
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
uint8_t compressed_fabric_id[sizeof(uint64_t)];
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
if (CHIP_NO_ERROR !=
commissioner::get_device_commissioner()->GetCompressedFabricIdBytes(compressed_fabric_id_span)) {
ESP_LOGE(TAG, "Failed to get the compressed fabric_id");
return ESP_FAIL;
}
if (key_policy != 0 && key_policy != 1) {
return ESP_ERR_INVALID_ARG;
}
GroupDataProvider::KeySet keyset(keyset_id, GroupDataProvider::SecurityPolicy(key_policy), 1);
GroupDataProvider::EpochKey epoch_key;
epoch_key.start_time = validity_time;
uint8_t epoch_key_buf[GroupDataProvider::EpochKey::kLengthBytes];
if (oct_str_to_byte_arr(epoch_key_oct_str, epoch_key_buf) != GroupDataProvider::EpochKey::kLengthBytes) {
ESP_LOGE(TAG, "The epoch key octstring is wrong");
return ESP_ERR_INVALID_ARG;
}
memcpy(epoch_key.key, epoch_key_buf, GroupDataProvider::EpochKey::kLengthBytes);
memcpy(keyset.epoch_keys, &epoch_key, sizeof(GroupDataProvider::EpochKey));
if (CHIP_NO_ERROR != group_data_provider->SetKeySet(fabric_index, compressed_fabric_id_span, keyset)) {
ESP_LOGE(TAG, "Failed to set keyset");
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t remove_keyset(uint16_t keyset_id)
{
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
size_t index = 0;
CHIP_ERROR err = CHIP_NO_ERROR;
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
GroupDataProvider::GroupKey group_key;
while (iter->Next(group_key)) {
if (group_key.keyset_id == keyset_id) {
err = group_data_provider->RemoveGroupKeyAt(fabric_index, index);
if (err != CHIP_NO_ERROR) {
break;
}
}
index++;
}
iter->Release();
if (err == CHIP_NO_ERROR) {
return ESP_OK;
}
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveKeySet(fabric_index, keyset_id), ESP_FAIL, TAG,
"Failed to remove the keyset");
return ESP_OK;
}
} // namespace group_settings
} // namespace controller
} // namespace esp_matter