3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * Provides an implementation of the CHIP GroupKeyStore interface
21 * for Qorvo platforms.
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
26 #include <platform/qpg6100/GroupKeyStoreImpl.h>
28 using namespace ::chip;
29 using namespace ::chip::Profiles::Security::AppKeys;
32 namespace DeviceLayer {
35 CHIP_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, ChipGroupKey & key)
39 // Iterate over all the GroupKey NVM records looking for a matching key...
40 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
41 [keyId, &key](const Key & nvmKey, const size_t & length) -> CHIP_ERROR {
44 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
47 // Read the NVM element data into the buffer.
48 err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
50 // Decode the CHIP key id for the current key.
51 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
54 // If it matches the key we're looking for...
55 if (curKeyId == keyId)
57 // Decode the associated key data.
58 err2 = DecodeGroupKey(buf, keyLen, key);
61 // End the iteration by returning a CHIP_END_OF_INPUT result.
62 ExitNow(err2 = CHIP_END_OF_INPUT);
69 // Modify error code for return.
72 case CHIP_END_OF_INPUT:
73 err = CHIP_NO_ERROR; // Match found.
76 err = CHIP_ERROR_KEY_NOT_FOUND; // Match not found.
85 CHIP_ERROR GroupKeyStoreImpl::StoreGroupKey(const ChipGroupKey & key)
89 // Delete any existing group key with the same id (this may or may not exit).
90 DeleteGroupKey(key.KeyId); // no error checking here.
92 // Iterate over all the GroupKey nvm3 records looking for the first
93 // empty NVM key where we can store the data. (Note- use arg addNewrecord=true)
94 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, true,
95 [&key](const Key & nvmKey, const size_t & length) -> CHIP_ERROR {
98 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
100 // Encode the key for storage in an NVM record.
101 err2 = EncodeGroupKey(key, buf, sizeof(buf), keyLen);
104 // Write the encoded binary data into the NVM object.
105 err2 = WriteConfigValueBin(nvmKey, buf, keyLen);
108 // End the iteration by returning a CHIP_END_OF_INPUT result.
109 ExitNow(err2 = CHIP_END_OF_INPUT);
115 // Modify error code for return.
118 case CHIP_END_OF_INPUT:
119 err = CHIP_NO_ERROR; // Key entry was stored.
122 err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not stored.
128 if (err == CHIP_NO_ERROR)
130 #if CHIP_PROGRESS_LOGGING
132 char extraKeyInfo[32];
133 if (ChipKeyId::IsAppEpochKey(key.KeyId))
135 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", start time %" PRId32, key.StartTime);
137 else if (ChipKeyId::IsAppGroupMasterKey(key.KeyId))
139 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", global id 0x%08" PRIX32, key.GlobalId);
146 #if CHIP_CONFIG_SECURITY_TEST_MODE
147 ChipLogProgress(SecurityManager,
148 "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 ", data 0x%02" PRIX8 "...%s", key.KeyId,
149 ChipKeyId::DescribeKey(key.KeyId), key.KeyLen, key.Key[0], extraKeyInfo);
151 ChipLogProgress(SecurityManager, "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 "%s", key.KeyId,
152 ChipKeyId::DescribeKey(key.KeyId), key.KeyLen, extraKeyInfo);
156 #endif // CHIP_PROGRESS_LOGGING
162 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
166 // Iterate over all the GroupKey NVM records looking for a matching key...
167 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
168 [keyId](const Key & nvmKey, const size_t & length) -> CHIP_ERROR {
171 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
174 // Read the NVM element data into the buffer.
175 err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
178 // Decode the CHIP key id for the current group key.
179 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
182 // If it matches the key we are looking for, delete the NVM record.
183 if (curKeyId == keyId)
185 err2 = ClearConfigValue(nvmKey);
186 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
188 // End the iteration by returning a CHIP_END_OF_INPUT result.
189 ExitNow(err2 = CHIP_END_OF_INPUT);
196 // Modify error code for return.
199 case CHIP_END_OF_INPUT:
200 err = CHIP_NO_ERROR; // Key entry was deleted.
203 err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not deleted.
212 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
216 // Iterate over all the GroupKey NVM records looking for a matching key...
217 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
218 [keyType](const Key & nvmKey, const size_t & length) -> CHIP_ERROR {
221 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
224 // Read the NVM element data into the buffer.
225 err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
228 // Decode the CHIP key id for the current group key.
229 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
232 // If the current key matches the type we are looking for, delete the NVM record.
233 if (ChipKeyId::GetType(curKeyId) == keyType)
235 err2 = ClearConfigValue(nvmKey);
236 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
246 CHIP_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t keyType, uint32_t * keyIds, uint8_t keyIdsArraySize, uint8_t & keyCount)
252 // Iterate over all the GroupKey records looking for keys of the specified type...
253 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
254 [keyType, keyIds, keyIdsArraySize, &keyCount](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR {
257 uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
260 // Read the NVM element data into the buffer.
261 err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
264 // Decode the CHIP key id for the current group key.
265 err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
268 // If the current key matches the type we're looking for, add it to the keyIds array.
269 if ((keyType == ChipKeyId::kType_None) || (ChipKeyId::GetType(curKeyId) == keyType))
271 keyIds[keyCount++] = curKeyId;
273 // Stop iterating if there's no more room in the keyIds array.
274 VerifyOrExit(keyCount < keyIdsArraySize, err2 = CHIP_ERROR_BUFFER_TOO_SMALL);
281 // Simply return a truncated list if there are more matching keys than will fit in the array.
282 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
290 CHIP_ERROR GroupKeyStoreImpl::Clear(void)
294 // Iterate over all the GroupKey NVM records deleting each one...
295 err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
296 [](const Key & nvmKey, const size_t & length) -> CHIP_ERROR {
299 err2 = ClearConfigValue(nvmKey);
309 CHIP_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
313 err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
314 if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
316 LastUsedEpochKeyId = ChipKeyId::kNone;
322 CHIP_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
324 return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
327 CHIP_ERROR GroupKeyStoreImpl::Init()
330 return CHIP_NO_ERROR;
333 CHIP_ERROR GroupKeyStoreImpl::EncodeGroupKey(const ChipGroupKey & key, uint8_t * buf, size_t bufSize, size_t & encodedKeyLen)
335 CHIP_ERROR err = CHIP_NO_ERROR;
338 VerifyOrExit(bufSize >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_BUFFER_TOO_SMALL);
340 Encoding::LittleEndian::Write32(p, key.KeyId);
341 Encoding::LittleEndian::Write32(p, key.StartTime);
342 Encoding::Write8(p, key.KeyLen);
343 memcpy(p, key.Key, key.KeyLen);
346 encodedKeyLen = p - buf;
352 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKeyId(const uint8_t * encodedKey, size_t encodedKeyLen, uint32_t & keyId)
354 CHIP_ERROR err = CHIP_NO_ERROR;
356 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
358 keyId = Encoding::LittleEndian::Get32(encodedKey);
364 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKey(const uint8_t * encodedKey, size_t encodedKeyLen, ChipGroupKey & key)
366 CHIP_ERROR err = CHIP_NO_ERROR;
367 const uint8_t * p = encodedKey;
369 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
371 key.KeyId = Encoding::LittleEndian::Read32(p);
372 key.StartTime = Encoding::LittleEndian::Read32(p);
373 key.KeyLen = Encoding::Read8(p);
375 VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_INVALID_ARGUMENT);
377 memcpy(key.Key, p, key.KeyLen);
383 } // namespace Internal
384 } // namespace DeviceLayer