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