Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / qpg6100 / GroupKeyStoreImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /**
19  *    @file
20  *          Provides an implementation of the CHIP GroupKeyStore interface
21  *          for Qorvo platforms.
22  */
23
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
25
26 #include <platform/qpg6100/GroupKeyStoreImpl.h>
27
28 using namespace ::chip;
29 using namespace ::chip::Profiles::Security::AppKeys;
30
31 namespace chip {
32 namespace DeviceLayer {
33 namespace Internal {
34
35 CHIP_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, ChipGroupKey & key)
36 {
37     CHIP_ERROR err;
38
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 {
42                             CHIP_ERROR err2;
43                             size_t keyLen;
44                             uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
45                             uint32_t curKeyId;
46
47                             // Read the NVM element data into the buffer.
48                             err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
49
50                             // Decode the CHIP key id for the current key.
51                             err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
52                             SuccessOrExit(err2);
53
54                             // If it matches the key we're looking for...
55                             if (curKeyId == keyId)
56                             {
57                                 // Decode the associated key data.
58                                 err2 = DecodeGroupKey(buf, keyLen, key);
59                                 SuccessOrExit(err2);
60
61                                 // End the iteration by returning a CHIP_END_OF_INPUT result.
62                                 ExitNow(err2 = CHIP_END_OF_INPUT);
63                             }
64
65                         exit:
66                             return err2;
67                         });
68
69     // Modify error code for return.
70     switch (err)
71     {
72     case CHIP_END_OF_INPUT:
73         err = CHIP_NO_ERROR; // Match found.
74         break;
75     case CHIP_NO_ERROR:
76         err = CHIP_ERROR_KEY_NOT_FOUND; // Match not found.
77         break;
78     default:
79         break;
80     }
81
82     return err;
83 }
84
85 CHIP_ERROR GroupKeyStoreImpl::StoreGroupKey(const ChipGroupKey & key)
86 {
87     CHIP_ERROR err;
88
89     // Delete any existing group key with the same id (this may or may not exit).
90     DeleteGroupKey(key.KeyId); // no error checking here.
91
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 {
96                             CHIP_ERROR err2;
97                             size_t keyLen;
98                             uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
99
100                             // Encode the key for storage in an NVM record.
101                             err2 = EncodeGroupKey(key, buf, sizeof(buf), keyLen);
102                             SuccessOrExit(err2);
103
104                             // Write the encoded binary data into the NVM object.
105                             err2 = WriteConfigValueBin(nvmKey, buf, keyLen);
106                             SuccessOrExit(err2);
107
108                             // End the iteration by returning a CHIP_END_OF_INPUT result.
109                             ExitNow(err2 = CHIP_END_OF_INPUT);
110
111                         exit:
112                             return err2;
113                         });
114
115     // Modify error code for return.
116     switch (err)
117     {
118     case CHIP_END_OF_INPUT:
119         err = CHIP_NO_ERROR; // Key entry was stored.
120         break;
121     case CHIP_NO_ERROR:
122         err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not stored.
123         break;
124     default:
125         break;
126     }
127
128     if (err == CHIP_NO_ERROR)
129     {
130 #if CHIP_PROGRESS_LOGGING
131         {
132             char extraKeyInfo[32];
133             if (ChipKeyId::IsAppEpochKey(key.KeyId))
134             {
135                 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", start time %" PRId32, key.StartTime);
136             }
137             else if (ChipKeyId::IsAppGroupMasterKey(key.KeyId))
138             {
139                 snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", global id 0x%08" PRIX32, key.GlobalId);
140             }
141             else
142             {
143                 extraKeyInfo[0] = 0;
144             }
145
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);
150 #else
151             ChipLogProgress(SecurityManager, "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 "%s", key.KeyId,
152                             ChipKeyId::DescribeKey(key.KeyId), key.KeyLen, extraKeyInfo);
153 #endif
154         }
155
156 #endif // CHIP_PROGRESS_LOGGING
157     }
158
159     return err;
160 }
161
162 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
163 {
164     CHIP_ERROR err;
165
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 {
169                             CHIP_ERROR err2;
170                             size_t keyLen;
171                             uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
172                             uint32_t curKeyId;
173
174                             // Read the NVM element data into the buffer.
175                             err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
176                             SuccessOrExit(err2);
177
178                             // Decode the CHIP key id for the current group key.
179                             err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
180                             SuccessOrExit(err2);
181
182                             // If it matches the key we are looking for, delete the NVM record.
183                             if (curKeyId == keyId)
184                             {
185                                 err2 = ClearConfigValue(nvmKey);
186                                 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
187
188                                 // End the iteration by returning a CHIP_END_OF_INPUT result.
189                                 ExitNow(err2 = CHIP_END_OF_INPUT);
190                             }
191
192                         exit:
193                             return err2;
194                         });
195
196     // Modify error code for return.
197     switch (err)
198     {
199     case CHIP_END_OF_INPUT:
200         err = CHIP_NO_ERROR; // Key entry was deleted.
201         break;
202     case CHIP_NO_ERROR:
203         err = CHIP_ERROR_KEY_NOT_FOUND; // Key entry was not deleted.
204         break;
205     default:
206         break;
207     }
208
209     return err;
210 }
211
212 CHIP_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
213 {
214     CHIP_ERROR err;
215
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 {
219                             CHIP_ERROR err2;
220                             size_t keyLen;
221                             uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
222                             uint32_t curKeyId;
223
224                             // Read the NVM element data into the buffer.
225                             err2 = ReadConfigValueBin(nvmKey, buf, sizeof(buf), keyLen);
226                             SuccessOrExit(err2);
227
228                             // Decode the CHIP key id for the current group key.
229                             err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
230                             SuccessOrExit(err2);
231
232                             // If the current key matches the type we are looking for, delete the NVM record.
233                             if (ChipKeyId::GetType(curKeyId) == keyType)
234                             {
235                                 err2 = ClearConfigValue(nvmKey);
236                                 ChipLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
237                             }
238
239                         exit:
240                             return err2;
241                         });
242
243     return err;
244 }
245
246 CHIP_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t keyType, uint32_t * keyIds, uint8_t keyIdsArraySize, uint8_t & keyCount)
247 {
248     CHIP_ERROR err;
249
250     keyCount = 0;
251
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 {
255                             CHIP_ERROR err2;
256                             size_t keyLen;
257                             uint8_t buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
258                             uint32_t curKeyId;
259
260                             // Read the NVM element data into the buffer.
261                             err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
262                             SuccessOrExit(err2);
263
264                             // Decode the CHIP key id for the current group key.
265                             err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
266                             SuccessOrExit(err2);
267
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))
270                             {
271                                 keyIds[keyCount++] = curKeyId;
272
273                                 // Stop iterating if there's no more room in the keyIds array.
274                                 VerifyOrExit(keyCount < keyIdsArraySize, err2 = CHIP_ERROR_BUFFER_TOO_SMALL);
275                             }
276
277                         exit:
278                             return err2;
279                         });
280
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)
283     {
284         err = CHIP_NO_ERROR;
285     }
286
287     return err;
288 }
289
290 CHIP_ERROR GroupKeyStoreImpl::Clear(void)
291 {
292     CHIP_ERROR err;
293
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 {
297                             CHIP_ERROR err2;
298
299                             err2 = ClearConfigValue(nvmKey);
300                             SuccessOrExit(err2);
301
302                         exit:
303                             return err2;
304                         });
305
306     return err;
307 }
308
309 CHIP_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
310 {
311     CHIP_ERROR err;
312
313     err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
314     if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
315     {
316         LastUsedEpochKeyId = ChipKeyId::kNone;
317         err                = CHIP_NO_ERROR;
318     }
319     return err;
320 }
321
322 CHIP_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
323 {
324     return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
325 }
326
327 CHIP_ERROR GroupKeyStoreImpl::Init()
328 {
329     // Nothing to do
330     return CHIP_NO_ERROR;
331 }
332
333 CHIP_ERROR GroupKeyStoreImpl::EncodeGroupKey(const ChipGroupKey & key, uint8_t * buf, size_t bufSize, size_t & encodedKeyLen)
334 {
335     CHIP_ERROR err = CHIP_NO_ERROR;
336     uint8_t * p    = buf;
337
338     VerifyOrExit(bufSize >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_BUFFER_TOO_SMALL);
339
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);
344     p += key.KeyLen;
345
346     encodedKeyLen = p - buf;
347
348 exit:
349     return err;
350 }
351
352 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKeyId(const uint8_t * encodedKey, size_t encodedKeyLen, uint32_t & keyId)
353 {
354     CHIP_ERROR err = CHIP_NO_ERROR;
355
356     VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
357
358     keyId = Encoding::LittleEndian::Get32(encodedKey);
359
360 exit:
361     return err;
362 }
363
364 CHIP_ERROR GroupKeyStoreImpl::DecodeGroupKey(const uint8_t * encodedKey, size_t encodedKeyLen, ChipGroupKey & key)
365 {
366     CHIP_ERROR err    = CHIP_NO_ERROR;
367     const uint8_t * p = encodedKey;
368
369     VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = CHIP_ERROR_INVALID_ARGUMENT);
370
371     key.KeyId     = Encoding::LittleEndian::Read32(p);
372     key.StartTime = Encoding::LittleEndian::Read32(p);
373     key.KeyLen    = Encoding::Read8(p);
374
375     VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize + key.KeyLen, err = CHIP_ERROR_INVALID_ARGUMENT);
376
377     memcpy(key.Key, p, key.KeyLen);
378
379 exit:
380     return err;
381 }
382
383 } // namespace Internal
384 } // namespace DeviceLayer
385 } // namespace chip
386 } // namespace chip