3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2019 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * Provides an implementation of the CHIP GroupKeyStore interface
22 * for platforms based on the Silicon Labs SDK.
24 /* this file behaves like a config.h, comes first */
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
27 #include <platform/EFR32/GroupKeyStoreImpl.h>
29 using namespace ::chip;
30 using namespace ::chip::Profiles::Security::AppKeys;
33 namespace DeviceLayer {
36 CHIP_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, ChipGroupKey & key)
40 // Iterate over all the GroupKey nvm3 records looking for a matching key...
41 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
42 [keyId, &key](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
45 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
48 // Read the nvm3 obj binary data data into the buffer.
49 err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
51 // Decode the CHIP key id for the current key.
52 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
55 // If it matches the key we're looking for...
56 if (curKeyId == keyId)
58 // Decode the associated key data.
59 err2 = DecodeGroupKey(buf, keyLen, key);
62 // End the iteration by returning a CHIP_END_OF_INPUT result.
63 ExitNow(err2 = CHIP_END_OF_INPUT);
70 // Modify error code for return.
73 case CHIP_END_OF_INPUT:
74 err = CHIP_NO_ERROR; // Match found.
77 err = CHIP_ERROR_KEY_NOT_FOUND; // Match not found.
86 CHIP_ERROR GroupKeyStoreImpl::StoreGroupKey(const ChipGroupKey & key)
90 // Delete any existing group key with the same id (this may or may not exit).
91 DeleteGroupKey(key.KeyId); // no error checking here.
93 // Iterate over all the GroupKey nvm3 records looking for the first
94 // empty nvm3 key where we can store the data. (Note- use arg addNewrecord=true)
95 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, true,
96 [&key](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
99 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
101 // Encode the key for storage in an nvm3 record.
102 err2 = EncodeGroupKey(key, buf, sizeof(buf), keyLen);
105 // Write the encoded binary data into the nvm3 object.
106 err2 = WriteConfigValueBin(nvm3Key, buf, keyLen);
109 // End the iteration by returning a CHIP_END_OF_INPUT result.
110 ExitNow(err2 = CHIP_END_OF_INPUT);
116 // Modify error code for return.
119 case CHIP_END_OF_INPUT:
120 err = CHIP_NO_ERROR; // Key entry was stored.
123 err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not stored.
129 if (err == CHIP_NO_ERROR)
131 #if CHIP_PROGRESS_LOGGING
133 char extraKeyInfo[32];
134 if (ChipKeyId::IsAppEpochKey(key.KeyId))
136 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", start time %" PRId32, key.StartTime);
138 else if (ChipKeyId::IsAppGroupMasterKey(key.KeyId))
140 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", global id 0x%08" PRIX32, key.GlobalId);
147 #if CHIP_CONFIG_SECURITY_TEST_MODE
148 ChipLogProgress(SecurityManager,
149 "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 ", data 0x%02" PRIX8 "...%s", key.KeyId,
150 ChipKeyId::DescribeKey(key.KeyId), key.KeyLen, key.Key[0], extraKeyInfo);
152 ChipLogProgress(SecurityManager, "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 "%s", key.KeyId,
153 ChipKeyId::DescribeKey(key.KeyId), key.KeyLen, extraKeyInfo);
157 #endif // CHIP_PROGRESS_LOGGING
163 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
167 // Iterate over all the GroupKey nvm3 records looking for a matching key...
168 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
169 [keyId](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
172 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
175 // Read the nvm3 obj binary data data into the buffer.
176 err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
179 // Decode the CHIP key id for the current group key.
180 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
183 // If it matches the key we are looking for, delete the nvm3 record.
184 if (curKeyId == keyId)
186 err2 = ClearConfigValue(nvm3Key);
187 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
189 // End the iteration by returning a CHIP_END_OF_INPUT result.
190 ExitNow(err2 = CHIP_END_OF_INPUT);
197 // Modify error code for return.
200 case CHIP_END_OF_INPUT:
201 err = CHIP_NO_ERROR; // Key entry was deleted.
204 err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not deleted.
213 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
217 // Iterate over all the GroupKey nvm3 records looking for a matching key...
218 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
219 [keyType](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
222 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
225 // Read the nvm3 obj binary data data into the buffer.
226 err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
229 // Decode the CHIP key id for the current group key.
230 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
233 // If the current key matches the type we are looking for, delete the nvm3 record.
234 if (ChipKeyId::GetType(curKeyId) == keyType)
236 err2 = ClearConfigValue(nvm3Key);
237 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
247 CHIP_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t keyType, uint32_t * keyIds, uint8_t keyIdsArraySize, uint8_t & keyCount)
253 // Iterate over all the GroupKey records looking for keys of the specified type...
254 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
255 [keyType, keyIds, keyIdsArraySize, &keyCount](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
258 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
261 // Read the nvm3 obj binary data data into the buffer.
262 err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
265 // Decode the CHIP key id for the current group key.
266 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
269 // If the current key matches the type we're looking for, add it to the keyIds array.
270 if ((keyType == ChipKeyId::kType_None) || (ChipKeyId::GetType(curKeyId) == keyType))
272 keyIds[keyCount++] = curKeyId;
274 // Stop iterating if there's no more room in the keyIds array.
275 VerifyOrExit(keyCount < keyIdsArraySize, err2 = CHIP_ERROR_BUFFER_TOO_SMALL);
282 // Simply return a truncated list if there are more matching keys than will fit in the array.
283 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
291 CHIP_ERROR GroupKeyStoreImpl::Clear(void)
295 // Iterate over all the GroupKey nvm3 records deleting each one...
296 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
297 [](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
300 err2 = ClearConfigValue(nvm3Key);
310 CHIP_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
314 err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
315 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
317 LastUsedEpochKeyId = ChipKeyId::kNone;
323 CHIP_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
325 return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
328 CHIP_ERROR GroupKeyStoreImpl::Init()
331 return CHIP_NO_ERROR;
334 CHIP_ERROR GroupKeyStoreImpl::EncodeGroupKey(const ChipGroupKey & key, uint8_t * buf, size_t bufSize, size_t & encodedKeyLen)
336 CHIP_ERROR err = CHIP_NO_ERROR;
339 VerifyOrExit(bufSize >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_BUFFER_TOO_SMALL);
341 Encoding::LittleEndian::Write32(p, key.KeyId);
342 Encoding::LittleEndian::Write32(p, key.StartTime);
343 Encoding::Write8(p, key.KeyLen);
344 memcpy(p, key.Key, key.KeyLen);
347 encodedKeyLen = p - buf;
353 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKeyId(const uint8_t * encodedKey, size_t encodedKeyLen, uint32_t & keyId)
355 CHIP_ERROR err = CHIP_NO_ERROR;
357 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
359 keyId = Encoding::LittleEndian::Get32(encodedKey);
365 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKey(const uint8_t * encodedKey, size_t encodedKeyLen, ChipGroupKey & key)
367 CHIP_ERROR err = CHIP_NO_ERROR;
368 const uint8_t * p = encodedKey;
370 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
372 key.KeyId = Encoding::LittleEndian::Read32(p);
373 key.StartTime = Encoding::LittleEndian::Read32(p);
374 key.KeyLen = Encoding::Read8(p);
376 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_INVALID_ARGUMENT);
378 memcpy(key.Key, p, key.KeyLen);
384 } // namespace Internal
385 } // namespace DeviceLayer