3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * Provides an implementation of the Chip GroupKeyStore interface
23 * for the ESP32 platform.
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
28 #include <platform/ESP32/GroupKeyStoreImpl.h>
31 #include "nvs_flash.h"
33 using namespace ::chip;
34 using namespace ::nl::Weave::Profiles::Security::AppKeys;
37 namespace DeviceLayer {
40 CHIP_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, ChipGroupKey & key)
44 char keyName[kMaxConfigKeyNameLength + 1];
45 ESP32Config::Key configKey{ kConfigNamespace_ChipConfig, keyName };
47 err = FormKeyName(keyId, keyName, sizeof(keyName));
50 err = ReadConfigValueBin(configKey, key.Key, sizeof(key.Key), keyLen);
51 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
53 err = CHIP_ERROR_KEY_NOT_FOUND;
57 if (keyId != ChipKeyId::kFabricSecret)
59 memcpy(&key.StartTime, key.Key + kChipAppGroupKeySize, sizeof(uint32_t));
60 keyLen -= sizeof(uint32_t);
70 CHIP_ERROR GroupKeyStoreImpl::StoreGroupKey(const ChipGroupKey & key)
74 char keyName[kMaxConfigKeyNameLength + 1];
75 uint8_t keyData[ChipGroupKey::MaxKeySize];
76 bool needClose = false;
77 bool indexUpdated = false;
79 err = FormKeyName(key.KeyId, keyName, sizeof(keyName));
82 err = AddKeyToIndex(key.KeyId, indexUpdated);
85 err = nvs_open(kConfigNamespace_ChipConfig, NVS_READWRITE, &handle);
89 memcpy(keyData, key.Key, ChipGroupKey::MaxKeySize);
90 if (key.KeyId != ChipKeyId::kFabricSecret)
92 memcpy(keyData + kChipAppGroupKeySize, (const void *) &key.StartTime, sizeof(uint32_t));
95 #if CHIP_PROGRESS_LOGGING
96 if (ChipKeyId::IsAppEpochKey(key.KeyId))
98 ChipLogProgress(DeviceLayer, "GroupKeyStore: storing epoch key %s/%s (key len %" PRId8 ", start time %" PRIu32 ")",
99 kConfigNamespace_ChipConfig, keyName, key.KeyLen, key.StartTime);
101 else if (ChipKeyId::IsAppGroupMasterKey(key.KeyId))
103 ChipLogProgress(DeviceLayer, "GroupKeyStore: storing app master key %s/%s (key len %" PRId8 ", global id 0x%" PRIX32 ")",
104 kConfigNamespace_ChipConfig, keyName, key.KeyLen, key.GlobalId);
108 const char * keyType = (ChipKeyId::IsAppRootKey(key.KeyId)) ? "root" : "general";
109 ChipLogProgress(DeviceLayer, "GroupKeyStore: storing %s key %s/%s (key len %" PRId8 ")", keyType,
110 kConfigNamespace_ChipConfig, keyName, key.KeyLen);
112 #endif // CHIP_PROGRESS_LOGGING
114 err = nvs_set_blob(handle, keyName, keyData, ChipGroupKey::MaxKeySize);
119 err = WriteKeyIndex(handle);
123 // Commit the value to the persistent store.
124 err = nvs_commit(handle);
132 if (err != CHIP_NO_ERROR && indexUpdated)
136 ClearSecretData(keyData, sizeof(keyData));
140 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
142 return DeleteKeyOrKeys(keyId, ChipKeyId::kType_None);
145 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
147 return DeleteKeyOrKeys(ChipKeyId::kNone, keyType);
150 CHIP_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t keyType, uint32_t * keyIds, uint8_t keyIdsArraySize, uint8_t & keyCount)
154 for (uint8_t i = 0; i < mNumKeys && keyCount < keyIdsArraySize; i++)
156 if (keyType == ChipKeyId::kType_None || ChipKeyId::GetType(mKeyIndex[i]) == keyType)
158 keyIds[keyCount++] = mKeyIndex[i];
162 return CHIP_NO_ERROR;
165 CHIP_ERROR GroupKeyStoreImpl::Clear(void)
167 return DeleteKeyOrKeys(ChipKeyId::kNone, ChipKeyId::kType_None);
170 CHIP_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
174 err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
175 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
177 LastUsedEpochKeyId = ChipKeyId::kNone;
183 CHIP_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
185 return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
188 CHIP_ERROR GroupKeyStoreImpl::Init()
191 size_t indexSizeBytes;
193 err = ReadConfigValueBin(kConfigKey_GroupKeyIndex, (uint8_t *) mKeyIndex, sizeof(mKeyIndex), indexSizeBytes);
194 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
201 mNumKeys = indexSizeBytes / sizeof(uint32_t);
207 CHIP_ERROR GroupKeyStoreImpl::AddKeyToIndex(uint32_t keyId, bool & indexUpdated)
209 CHIP_ERROR err = CHIP_NO_ERROR;
211 indexUpdated = false;
213 for (uint8_t i = 0; i < mNumKeys; i++)
215 if (mKeyIndex[i] == keyId)
217 ExitNow(err = CHIP_NO_ERROR);
221 VerifyOrExit(mNumKeys < kMaxGroupKeys, err = CHIP_ERROR_TOO_MANY_KEYS);
223 mKeyIndex[mNumKeys++] = keyId;
230 CHIP_ERROR GroupKeyStoreImpl::WriteKeyIndex(nvs_handle handle)
232 ChipLogProgress(DeviceLayer, "GroupKeyStore: writing key index %s/%s (num keys %" PRIu8 ")", kConfigKey_GroupKeyIndex.Namespace,
233 kConfigKey_GroupKeyIndex.Name, mNumKeys);
234 return nvs_set_blob(handle, kConfigKey_GroupKeyIndex.Name, mKeyIndex, mNumKeys * sizeof(uint32_t));
237 CHIP_ERROR GroupKeyStoreImpl::DeleteKeyOrKeys(uint32_t targetKeyId, uint32_t targetKeyType)
239 CHIP_ERROR err = CHIP_NO_ERROR;
241 char keyName[kMaxConfigKeyNameLength + 1];
242 bool needClose = false;
244 for (uint8_t i = 0; i < mNumKeys;)
246 uint32_t curKeyId = mKeyIndex[i];
248 if ((targetKeyId == ChipKeyId::kNone && targetKeyType == ChipKeyId::kType_None) || curKeyId == targetKeyId ||
249 ChipKeyId::GetType(curKeyId) == targetKeyType)
253 err = nvs_open(kConfigNamespace_ChipConfig, NVS_READWRITE, &handle);
258 err = FormKeyName(curKeyId, keyName, sizeof(keyName));
261 err = nvs_erase_key(handle, keyName);
262 #if CHIP_PROGRESS_LOGGING
265 const char * keyType;
266 if (ChipKeyId::IsAppRootKey(curKeyId))
270 else if (ChipKeyId::IsAppGroupMasterKey(curKeyId))
272 keyType = "app master";
274 else if (ChipKeyId::IsAppEpochKey(curKeyId))
282 ChipLogProgress(DeviceLayer, "GroupKeyStore: erasing %s key %s/%s", keyType, kConfigNamespace_ChipConfig, keyName);
285 #endif // CHIP_PROGRESS_LOGGING
286 if (err == ESP_ERR_NVS_NOT_FOUND)
294 memmove(&mKeyIndex[i], &mKeyIndex[i + 1], (mNumKeys - i) * sizeof(uint32_t));
304 err = WriteKeyIndex(handle);
307 // Commit to the persistent store.
308 err = nvs_commit(handle);
320 CHIP_ERROR GroupKeyStoreImpl::FormKeyName(uint32_t keyId, char * buf, size_t bufSize)
322 CHIP_ERROR err = CHIP_NO_ERROR;
324 VerifyOrExit(bufSize >= kMaxConfigKeyNameLength, err = CHIP_ERROR_BUFFER_TOO_SMALL);
326 if (keyId == ChipKeyId::kFabricSecret)
328 strcpy(buf, kConfigKey_FabricSecret.Name);
332 snprintf(buf, bufSize, "%s%08" PRIX32, kGroupKeyNamePrefix, keyId);
339 } // namespace Internal
340 } // namespace DeviceLayer