Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021-2022 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 : #include <credentials/GroupDataProviderImpl.h>
18 : #include <crypto/CHIPCryptoPAL.h>
19 : #include <lib/core/TLV.h>
20 : #include <lib/support/CodeUtils.h>
21 : #include <lib/support/CommonPersistentData.h>
22 : #include <lib/support/DefaultStorageKeyAllocator.h>
23 : #include <lib/support/PersistentData.h>
24 : #include <lib/support/Pool.h>
25 : #include <stdlib.h>
26 :
27 : namespace chip {
28 : namespace Credentials {
29 :
30 : using GroupInfo = GroupDataProvider::GroupInfo;
31 : using GroupKey = GroupDataProvider::GroupKey;
32 : using GroupEndpoint = GroupDataProvider::GroupEndpoint;
33 : using EpochKey = GroupDataProvider::EpochKey;
34 : using KeySet = GroupDataProvider::KeySet;
35 : using GroupSession = GroupDataProvider::GroupSession;
36 :
37 : struct FabricList : public CommonPersistentData::FabricList
38 : {
39 993 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
40 : {
41 993 : key = DefaultStorageKeyAllocator::GroupFabricList();
42 993 : return CHIP_NO_ERROR;
43 : }
44 : };
45 :
46 : constexpr size_t kPersistentBufferMax = 128;
47 :
48 : struct LinkedData : public PersistableData<kPersistentBufferMax>
49 : {
50 : static constexpr uint16_t kMinLinkId = 1;
51 :
52 66 : LinkedData() = default;
53 617 : LinkedData(uint16_t linked_id) : id(linked_id) {}
54 : uint16_t id = kMinLinkId;
55 : uint16_t index = 0;
56 : uint16_t next = 0;
57 : uint16_t prev = 0;
58 : uint16_t max_id = 0;
59 : bool first = true;
60 : };
61 :
62 : struct FabricData : public PersistableData<kPersistentBufferMax>
63 : {
64 3930 : static constexpr TLV::Tag TagFirstGroup() { return TLV::ContextTag(1); }
65 3930 : static constexpr TLV::Tag TagGroupCount() { return TLV::ContextTag(2); }
66 3930 : static constexpr TLV::Tag TagFirstMap() { return TLV::ContextTag(3); }
67 3930 : static constexpr TLV::Tag TagMapCount() { return TLV::ContextTag(4); }
68 3930 : static constexpr TLV::Tag TagFirstKeyset() { return TLV::ContextTag(5); }
69 3930 : static constexpr TLV::Tag TagKeysetCount() { return TLV::ContextTag(6); }
70 3930 : static constexpr TLV::Tag TagNext() { return TLV::ContextTag(7); }
71 :
72 : chip::FabricIndex fabric_index = kUndefinedFabricIndex;
73 : chip::GroupId first_group = kUndefinedGroupId;
74 : uint16_t group_count = 0;
75 : uint16_t first_map = 0;
76 : uint16_t map_count = 0;
77 : chip::KeysetId first_keyset = kInvalidKeysetId;
78 : uint16_t keyset_count = 0;
79 : chip::FabricIndex next = kUndefinedFabricIndex;
80 :
81 23 : FabricData() = default;
82 3279 : FabricData(chip::FabricIndex fabric) : fabric_index(fabric) {}
83 :
84 4170 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
85 : {
86 4170 : VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
87 4168 : key = DefaultStorageKeyAllocator::FabricGroups(fabric_index);
88 4168 : return CHIP_NO_ERROR;
89 : }
90 :
91 3319 : void Clear() override
92 : {
93 3319 : first_group = kUndefinedGroupId;
94 3319 : group_count = 0;
95 3319 : first_keyset = kInvalidKeysetId;
96 3319 : keyset_count = 0;
97 3319 : next = kUndefinedFabricIndex;
98 3319 : }
99 :
100 830 : CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
101 : {
102 : TLV::TLVType container;
103 830 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
104 :
105 830 : ReturnErrorOnFailure(writer.Put(TagFirstGroup(), static_cast<uint16_t>(first_group)));
106 830 : ReturnErrorOnFailure(writer.Put(TagGroupCount(), static_cast<uint16_t>(group_count)));
107 830 : ReturnErrorOnFailure(writer.Put(TagFirstMap(), static_cast<uint16_t>(first_map)));
108 830 : ReturnErrorOnFailure(writer.Put(TagMapCount(), static_cast<uint16_t>(map_count)));
109 830 : ReturnErrorOnFailure(writer.Put(TagFirstKeyset(), static_cast<uint16_t>(first_keyset)));
110 830 : ReturnErrorOnFailure(writer.Put(TagKeysetCount(), static_cast<uint16_t>(keyset_count)));
111 830 : ReturnErrorOnFailure(writer.Put(TagNext(), static_cast<uint16_t>(next)));
112 :
113 830 : return writer.EndContainer(container);
114 : }
115 3100 : CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
116 : {
117 3100 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
118 3100 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
119 :
120 : TLV::TLVType container;
121 3100 : ReturnErrorOnFailure(reader.EnterContainer(container));
122 :
123 : // first_group
124 3100 : ReturnErrorOnFailure(reader.Next(TagFirstGroup()));
125 3100 : ReturnErrorOnFailure(reader.Get(first_group));
126 : // group_count
127 3100 : ReturnErrorOnFailure(reader.Next(TagGroupCount()));
128 3100 : ReturnErrorOnFailure(reader.Get(group_count));
129 : // first_map
130 3100 : ReturnErrorOnFailure(reader.Next(TagFirstMap()));
131 3100 : ReturnErrorOnFailure(reader.Get(first_map));
132 : // map_count
133 3100 : ReturnErrorOnFailure(reader.Next(TagMapCount()));
134 3100 : ReturnErrorOnFailure(reader.Get(map_count));
135 : // first_keyset
136 3100 : ReturnErrorOnFailure(reader.Next(TagFirstKeyset()));
137 3100 : ReturnErrorOnFailure(reader.Get(first_keyset));
138 : // keyset_count
139 3100 : ReturnErrorOnFailure(reader.Next(TagKeysetCount()));
140 3100 : ReturnErrorOnFailure(reader.Get(keyset_count));
141 : // next
142 3100 : ReturnErrorOnFailure(reader.Next(TagNext()));
143 3100 : ReturnErrorOnFailure(reader.Get(next));
144 :
145 3100 : return reader.ExitContainer(container);
146 : }
147 :
148 : // Register the fabric in the fabrics' linked-list
149 830 : CHIP_ERROR Register(PersistentStorageDelegate * storage)
150 : {
151 830 : FabricList fabric_list;
152 830 : CHIP_ERROR err = fabric_list.Load(storage);
153 1660 : if (CHIP_ERROR_NOT_FOUND == err)
154 : {
155 : // New fabric list
156 91 : fabric_list.first_entry = fabric_index;
157 91 : fabric_list.entry_count = 1;
158 91 : return fabric_list.Save(storage);
159 : }
160 739 : ReturnErrorOnFailure(err);
161 :
162 : // Existing fabric list, search for existing entry
163 739 : FabricData fabric(fabric_list.first_entry);
164 795 : for (size_t i = 0; i < fabric_list.entry_count; i++)
165 : {
166 774 : err = fabric.Load(storage);
167 1548 : if (CHIP_NO_ERROR != err)
168 : {
169 0 : break;
170 : }
171 774 : if (fabric.fabric_index == this->fabric_index)
172 : {
173 : // Fabric already registered
174 718 : return CHIP_NO_ERROR;
175 : }
176 56 : fabric.fabric_index = fabric.next;
177 : }
178 : // Add this fabric to the fabric list
179 21 : this->next = fabric_list.first_entry;
180 21 : fabric_list.first_entry = this->fabric_index;
181 21 : fabric_list.entry_count++;
182 21 : return fabric_list.Save(storage);
183 830 : }
184 :
185 : // Remove the fabric from the fabrics' linked list
186 23 : CHIP_ERROR Unregister(PersistentStorageDelegate * storage) const
187 : {
188 23 : FabricList fabric_list;
189 23 : CHIP_ERROR err = fabric_list.Load(storage);
190 48 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
191 :
192 : // Existing fabric list, search for existing entry
193 23 : FabricData fabric(fabric_list.first_entry);
194 23 : FabricData prev;
195 :
196 33 : for (size_t i = 0; i < fabric_list.entry_count; i++)
197 : {
198 29 : err = fabric.Load(storage);
199 58 : if (CHIP_NO_ERROR != err)
200 : {
201 0 : break;
202 : }
203 29 : if (fabric.fabric_index == this->fabric_index)
204 : {
205 : // Fabric found
206 19 : if (i == 0)
207 : {
208 : // Remove first fabric
209 10 : fabric_list.first_entry = this->next;
210 : }
211 : else
212 : {
213 : // Remove intermediate fabric
214 9 : prev.next = this->next;
215 9 : ReturnErrorOnFailure(prev.Save(storage));
216 : }
217 19 : VerifyOrReturnError(fabric_list.entry_count > 0, CHIP_ERROR_INTERNAL);
218 19 : fabric_list.entry_count--;
219 19 : return fabric_list.Save(storage);
220 : }
221 10 : prev = fabric;
222 10 : fabric.fabric_index = fabric.next;
223 : }
224 : // Fabric not in the list
225 4 : return CHIP_ERROR_NOT_FOUND;
226 23 : }
227 :
228 : // Check the fabric is registered in the fabrics' linked list
229 : CHIP_ERROR Validate(PersistentStorageDelegate * storage) const
230 : {
231 : FabricList fabric_list;
232 : ReturnErrorOnFailure(fabric_list.Load(storage));
233 :
234 : // Existing fabric list, search for existing entry
235 : FabricData fabric(fabric_list.first_entry);
236 :
237 : for (size_t i = 0; i < fabric_list.entry_count; i++)
238 : {
239 : ReturnErrorOnFailure(fabric.Load(storage));
240 : if (fabric.fabric_index == this->fabric_index)
241 : {
242 : return CHIP_NO_ERROR;
243 : }
244 : fabric.fabric_index = fabric.next;
245 : }
246 : // Fabric not in the list
247 : return CHIP_ERROR_NOT_FOUND;
248 : }
249 :
250 830 : CHIP_ERROR Save(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method)
251 : {
252 830 : ReturnErrorOnFailure(Register(storage));
253 830 : return PersistableData::Save(storage);
254 : }
255 :
256 23 : CHIP_ERROR Delete(PersistentStorageDelegate * storage) // NOLINT(bugprone-derived-method-shadowing-base-method)
257 : {
258 23 : ReturnErrorOnFailure(Unregister(storage));
259 19 : return PersistableData::Delete(storage);
260 : }
261 : };
262 :
263 : struct GroupData : public GroupDataProvider::GroupInfo, PersistableData<kPersistentBufferMax>
264 : {
265 4608 : static constexpr TLV::Tag TagName() { return TLV::ContextTag(1); }
266 4608 : static constexpr TLV::Tag TagFirstEndpoint() { return TLV::ContextTag(2); }
267 4608 : static constexpr TLV::Tag TagEndpointCount() { return TLV::ContextTag(3); }
268 4608 : static constexpr TLV::Tag TagNext() { return TLV::ContextTag(4); }
269 4608 : static constexpr TLV::Tag TagFlags() { return TLV::ContextTag(5); }
270 :
271 : chip::FabricIndex fabric_index = kUndefinedFabricIndex;
272 : chip::EndpointId first_endpoint = kInvalidEndpointId;
273 : uint16_t endpoint_count = 0;
274 : uint16_t index = 0;
275 : chip::GroupId next = 0;
276 : chip::GroupId prev = 0;
277 : bool first = true;
278 :
279 1595 : GroupData() : GroupInfo(nullptr){};
280 : GroupData(chip::FabricIndex fabric) : fabric_index(fabric) {}
281 1238 : GroupData(chip::FabricIndex fabric, chip::GroupId group) : GroupInfo(group, nullptr), fabric_index(fabric) {}
282 :
283 4648 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
284 : {
285 4648 : VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
286 4648 : key = DefaultStorageKeyAllocator::FabricGroup(fabric_index, group_id);
287 4648 : return CHIP_NO_ERROR;
288 : }
289 :
290 3317 : void Clear() override
291 : {
292 3317 : SetName(CharSpan());
293 3317 : first_endpoint = kInvalidEndpointId;
294 3317 : endpoint_count = 0;
295 3317 : next = 0;
296 3317 : flags = 0;
297 3317 : }
298 :
299 1292 : CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
300 : {
301 : TLV::TLVType container;
302 1292 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
303 :
304 1292 : size_t name_size = strnlen(name, GroupDataProvider::GroupInfo::kGroupNameMax);
305 1292 : ReturnErrorOnFailure(writer.PutString(TagName(), name, static_cast<uint32_t>(name_size)));
306 1292 : ReturnErrorOnFailure(writer.Put(TagFirstEndpoint(), static_cast<uint16_t>(first_endpoint)));
307 1292 : ReturnErrorOnFailure(writer.Put(TagEndpointCount(), static_cast<uint16_t>(endpoint_count)));
308 1292 : ReturnErrorOnFailure(writer.Put(TagNext(), static_cast<uint16_t>(next)));
309 1292 : ReturnErrorOnFailure(writer.Put(TagFlags(), static_cast<uint8_t>(flags)));
310 1292 : return writer.EndContainer(container);
311 : }
312 :
313 3316 : CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
314 : {
315 3316 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
316 3316 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
317 :
318 : TLV::TLVType container;
319 3316 : ReturnErrorOnFailure(reader.EnterContainer(container));
320 :
321 : // name
322 3316 : ReturnErrorOnFailure(reader.Next(TagName()));
323 3316 : ReturnErrorOnFailure(reader.GetString(name, sizeof(name)));
324 3316 : size_t size = strnlen(name, kGroupNameMax);
325 3316 : name[size] = 0;
326 : // first_endpoint
327 3316 : ReturnErrorOnFailure(reader.Next(TagFirstEndpoint()));
328 3316 : ReturnErrorOnFailure(reader.Get(first_endpoint));
329 : // endpoint_count
330 3316 : ReturnErrorOnFailure(reader.Next(TagEndpointCount()));
331 3316 : ReturnErrorOnFailure(reader.Get(endpoint_count));
332 : // next
333 3316 : ReturnErrorOnFailure(reader.Next(TagNext()));
334 3316 : ReturnErrorOnFailure(reader.Get(next));
335 : // Groupcast
336 3316 : CHIP_ERROR err = reader.Next(TagFlags());
337 6632 : if (CHIP_NO_ERROR == err)
338 : {
339 : // flags
340 3316 : uint8_t value = 0;
341 3316 : ReturnErrorOnFailure(reader.Get(value));
342 3316 : flags = value;
343 : }
344 3316 : return reader.ExitContainer(container);
345 : }
346 :
347 83 : bool Get(PersistentStorageDelegate * storage, const FabricData & fabric, size_t target_index)
348 : {
349 83 : fabric_index = fabric.fabric_index;
350 83 : group_id = fabric.first_group;
351 83 : index = 0;
352 83 : first = true;
353 :
354 142 : while (index < fabric.group_count)
355 : {
356 248 : if (CHIP_NO_ERROR != Load(storage))
357 : {
358 0 : break;
359 : }
360 124 : if (index == target_index)
361 : {
362 : // Target index found
363 65 : return true;
364 : }
365 :
366 59 : first = false;
367 59 : prev = group_id;
368 59 : group_id = next;
369 59 : index++;
370 : }
371 :
372 18 : return false;
373 : }
374 :
375 1488 : bool Find(PersistentStorageDelegate * storage, const FabricData & fabric, chip::GroupId target_group)
376 : {
377 1488 : fabric_index = fabric.fabric_index;
378 1488 : group_id = fabric.first_group;
379 1488 : index = 0;
380 1488 : first = true;
381 :
382 2449 : while (index < fabric.group_count)
383 : {
384 3900 : if (CHIP_NO_ERROR != Load(storage))
385 : {
386 0 : break;
387 : }
388 1950 : if (group_id == target_group)
389 : {
390 : // Target index found
391 989 : return true;
392 : }
393 961 : first = false;
394 961 : prev = group_id;
395 961 : group_id = next;
396 961 : index++;
397 : }
398 499 : return false;
399 : }
400 : };
401 :
402 : struct KeyMapData : public GroupDataProvider::GroupKey, LinkedData
403 : {
404 1416 : static constexpr TLV::Tag TagGroupId() { return TLV::ContextTag(1); }
405 1416 : static constexpr TLV::Tag TagKeysetId() { return TLV::ContextTag(2); }
406 1416 : static constexpr TLV::Tag TagNext() { return TLV::ContextTag(3); }
407 :
408 : chip::FabricIndex fabric_index = kUndefinedFabricIndex;
409 : chip::GroupId group_id = kUndefinedGroupId;
410 : chip::KeysetId keyset_id = 0;
411 :
412 66 : KeyMapData(){};
413 617 : KeyMapData(chip::FabricIndex fabric, uint16_t link_id = 0, chip::GroupId group = kUndefinedGroupId, chip::KeysetId keyset = 0) :
414 617 : GroupKey(group, keyset), LinkedData(link_id), fabric_index(fabric)
415 617 : {}
416 :
417 1433 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
418 : {
419 1433 : VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
420 1433 : key = DefaultStorageKeyAllocator::FabricGroupKey(fabric_index, id);
421 1433 : return CHIP_NO_ERROR;
422 : }
423 :
424 965 : void Clear() override {}
425 :
426 451 : CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
427 : {
428 : TLV::TLVType container;
429 451 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
430 :
431 451 : ReturnErrorOnFailure(writer.Put(TagGroupId(), static_cast<uint16_t>(group_id)));
432 451 : ReturnErrorOnFailure(writer.Put(TagKeysetId(), static_cast<uint16_t>(keyset_id)));
433 451 : ReturnErrorOnFailure(writer.Put(TagNext(), static_cast<uint16_t>(next)));
434 451 : return writer.EndContainer(container);
435 : }
436 :
437 965 : CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
438 : {
439 965 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
440 965 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
441 :
442 : TLV::TLVType container;
443 965 : ReturnErrorOnFailure(reader.EnterContainer(container));
444 :
445 : // first_endpoint
446 965 : ReturnErrorOnFailure(reader.Next(TagGroupId()));
447 965 : ReturnErrorOnFailure(reader.Get(group_id));
448 : // endpoint_count
449 965 : ReturnErrorOnFailure(reader.Next(TagKeysetId()));
450 965 : ReturnErrorOnFailure(reader.Get(keyset_id));
451 : // next
452 965 : ReturnErrorOnFailure(reader.Next(TagNext()));
453 965 : ReturnErrorOnFailure(reader.Get(next));
454 :
455 965 : return reader.ExitContainer(container);
456 : }
457 :
458 300 : bool Get(PersistentStorageDelegate * storage, const FabricData & fabric, size_t target_index)
459 : {
460 300 : fabric_index = fabric.fabric_index;
461 300 : id = fabric.first_map;
462 300 : max_id = 0;
463 300 : index = 0;
464 300 : first = true;
465 :
466 609 : while (index < fabric.map_count)
467 : {
468 700 : if (CHIP_NO_ERROR != Load(storage))
469 : {
470 0 : break;
471 : }
472 350 : if (index == target_index)
473 : {
474 : // Target index found
475 41 : return true;
476 : }
477 309 : max_id = std::max(id, max_id);
478 309 : first = false;
479 309 : prev = id;
480 309 : id = next;
481 309 : index++;
482 : }
483 :
484 259 : id = static_cast<uint16_t>(max_id + 1);
485 259 : return false;
486 : }
487 :
488 264 : bool Find(PersistentStorageDelegate * storage, const FabricData & fabric, const GroupKey & map)
489 : {
490 264 : fabric_index = fabric.fabric_index;
491 264 : id = fabric.first_map;
492 264 : max_id = 0;
493 264 : index = 0;
494 264 : first = true;
495 :
496 531 : while (index < fabric.map_count)
497 : {
498 552 : if (CHIP_NO_ERROR != Load(storage))
499 : {
500 0 : break;
501 : }
502 276 : if ((group_id == map.group_id) && (keyset_id == map.keyset_id))
503 : {
504 : // Match found
505 9 : return true;
506 : }
507 267 : max_id = std::max(id, max_id);
508 267 : first = false;
509 267 : prev = id;
510 267 : id = next;
511 267 : index++;
512 : }
513 :
514 255 : id = static_cast<uint16_t>(max_id + 1);
515 255 : return false;
516 : }
517 :
518 : // returns index if the find_id is found, otherwise std::numeric_limits<size_t>::max
519 0 : size_t Find(PersistentStorageDelegate * storage, const FabricData & fabric, const KeysetId find_id)
520 : {
521 0 : fabric_index = fabric.fabric_index;
522 0 : id = fabric.first_map;
523 0 : max_id = 0;
524 0 : index = 0;
525 0 : first = true;
526 :
527 0 : while (index < fabric.map_count)
528 : {
529 0 : if (CHIP_NO_ERROR != Load(storage))
530 : {
531 0 : break;
532 : }
533 0 : if (keyset_id == find_id)
534 : {
535 : // Match found
536 0 : return index;
537 : }
538 0 : max_id = std::max(id, max_id);
539 0 : first = false;
540 0 : prev = id;
541 0 : id = next;
542 0 : index++;
543 : }
544 :
545 0 : id = static_cast<uint16_t>(max_id + 1);
546 0 : return std::numeric_limits<size_t>::max();
547 : }
548 : };
549 :
550 : struct EndpointData : GroupDataProvider::GroupEndpoint, PersistableData<kPersistentBufferMax>
551 : {
552 62302 : static constexpr TLV::Tag TagEndpoint() { return TLV::ContextTag(1); }
553 62302 : static constexpr TLV::Tag TagNext() { return TLV::ContextTag(2); }
554 :
555 : chip::FabricIndex fabric_index = kUndefinedFabricIndex;
556 : uint16_t index = 0;
557 : chip::EndpointId next = 0;
558 : chip::EndpointId prev = 0;
559 : bool first = true;
560 :
561 934 : EndpointData() = default;
562 1608 : EndpointData(chip::FabricIndex fabric, chip::GroupId group = kUndefinedGroupId,
563 1608 : chip::EndpointId endpoint = kInvalidEndpointId) :
564 : GroupEndpoint(group, endpoint),
565 1608 : fabric_index(fabric)
566 1608 : {}
567 :
568 62379 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
569 : {
570 62379 : VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
571 62379 : key = DefaultStorageKeyAllocator::FabricGroupEndpoint(fabric_index, group_id, endpoint_id);
572 62379 : return CHIP_NO_ERROR;
573 : }
574 :
575 60356 : void Clear() override { next = kInvalidEndpointId; }
576 :
577 1957 : CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
578 : {
579 : TLV::TLVType container;
580 1957 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
581 :
582 1957 : ReturnErrorOnFailure(writer.Put(TagEndpoint(), static_cast<uint16_t>(endpoint_id)));
583 1957 : ReturnErrorOnFailure(writer.Put(TagNext(), static_cast<uint16_t>(next)));
584 :
585 1957 : return writer.EndContainer(container);
586 : }
587 60345 : CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
588 : {
589 60345 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
590 60345 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
591 :
592 : TLV::TLVType container;
593 60345 : ReturnErrorOnFailure(reader.EnterContainer(container));
594 :
595 : // endpoint_id
596 60345 : ReturnErrorOnFailure(reader.Next(TagEndpoint()));
597 60345 : ReturnErrorOnFailure(reader.Get(endpoint_id));
598 : // next
599 60345 : ReturnErrorOnFailure(reader.Next(TagNext()));
600 60345 : ReturnErrorOnFailure(reader.Get(next));
601 :
602 60345 : return reader.ExitContainer(container);
603 : }
604 :
605 919 : bool Find(PersistentStorageDelegate * storage, const FabricData & fabric, const GroupData & group, chip::EndpointId target_id)
606 : {
607 919 : fabric_index = fabric.fabric_index;
608 919 : group_id = group.group_id;
609 919 : endpoint_id = group.first_endpoint;
610 919 : index = 0;
611 919 : first = true;
612 :
613 58641 : while (index < group.endpoint_count)
614 : {
615 115684 : if (CHIP_NO_ERROR != Load(storage))
616 : {
617 0 : break;
618 : }
619 57842 : if (this->endpoint_id == target_id)
620 : {
621 : // Match found
622 120 : return true;
623 : }
624 :
625 57722 : first = false;
626 57722 : prev = endpoint_id;
627 57722 : endpoint_id = next;
628 57722 : index++;
629 : }
630 :
631 799 : return false;
632 : }
633 : };
634 :
635 : struct KeySetData : PersistableData<kPersistentBufferMax>
636 : {
637 755 : static constexpr TLV::Tag TagPolicy() { return TLV::ContextTag(1); }
638 755 : static constexpr TLV::Tag TagNumKeys() { return TLV::ContextTag(2); }
639 755 : static constexpr TLV::Tag TagGroupCredentials() { return TLV::ContextTag(3); }
640 2265 : static constexpr TLV::Tag TagStartTime() { return TLV::ContextTag(4); }
641 2265 : static constexpr TLV::Tag TagKeyHash() { return TLV::ContextTag(5); }
642 2265 : static constexpr TLV::Tag TagKeyValue() { return TLV::ContextTag(6); }
643 755 : static constexpr TLV::Tag TagNext() { return TLV::ContextTag(7); }
644 :
645 : chip::FabricIndex fabric_index = kUndefinedFabricIndex;
646 : chip::KeysetId next = kInvalidKeysetId;
647 : chip::KeysetId prev = kInvalidKeysetId;
648 : bool first = true;
649 :
650 : uint16_t keyset_id = 0;
651 : GroupDataProvider::SecurityPolicy policy = GroupDataProvider::SecurityPolicy::kCacheAndSync;
652 : uint8_t keys_count = 0;
653 : Crypto::GroupOperationalCredentials operational_keys[KeySet::kEpochKeysMax];
654 :
655 446 : KeySetData() = default;
656 34 : KeySetData(chip::FabricIndex fabric, chip::KeysetId id) : fabric_index(fabric) { keyset_id = id; }
657 : KeySetData(chip::FabricIndex fabric, chip::KeysetId id, GroupDataProvider::SecurityPolicy policy_id, uint8_t num_keys) :
658 : fabric_index(fabric), keyset_id(id), policy(policy_id), keys_count(num_keys)
659 : {}
660 :
661 779 : CHIP_ERROR UpdateKey(StorageKeyName & key) const override
662 : {
663 779 : VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
664 779 : VerifyOrReturnError(kInvalidKeysetId != keyset_id, CHIP_ERROR_INVALID_KEY_ID);
665 779 : key = DefaultStorageKeyAllocator::FabricKeyset(fabric_index, keyset_id);
666 779 : return CHIP_NO_ERROR;
667 : }
668 :
669 510 : void Clear() override
670 : {
671 510 : policy = GroupDataProvider::SecurityPolicy::kCacheAndSync;
672 510 : keys_count = 0;
673 510 : memset(operational_keys, 0x00, sizeof(operational_keys));
674 510 : next = kInvalidKeysetId;
675 510 : }
676 :
677 4 : Crypto::GroupOperationalCredentials * GetCurrentGroupCredentials()
678 : {
679 : // An epoch key update SHALL order the keys from oldest to newest,
680 : // the current epoch key having the second newest time if time
681 : // synchronization is not achieved or guaranteed.
682 4 : switch (this->keys_count)
683 : {
684 1 : case 1:
685 : case 2:
686 1 : return &operational_keys[0];
687 3 : case 3:
688 3 : return &operational_keys[1];
689 0 : default:
690 0 : return nullptr;
691 : }
692 : }
693 :
694 245 : CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
695 : {
696 : TLV::TLVType container;
697 245 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));
698 :
699 : // policy
700 245 : ReturnErrorOnFailure(writer.Put(TagPolicy(), static_cast<uint16_t>(policy)));
701 : // keys_count
702 245 : ReturnErrorOnFailure(writer.Put(TagNumKeys(), static_cast<uint16_t>(keys_count)));
703 : // operational_keys
704 : {
705 : TLV::TLVType array, item;
706 245 : ReturnErrorOnFailure(writer.StartContainer(TagGroupCredentials(), TLV::kTLVType_Array, array));
707 245 : uint8_t keyCount = 0;
708 245 : uint64_t startTime = 0;
709 245 : uint16_t hash = 0;
710 : uint8_t encryptionKey[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
711 980 : for (auto & key : operational_keys)
712 : {
713 735 : startTime = 0;
714 735 : hash = 0;
715 735 : memset(encryptionKey, 0, sizeof(encryptionKey));
716 735 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, item));
717 :
718 735 : if (keyCount++ < keys_count)
719 : {
720 641 : startTime = key.start_time;
721 641 : hash = key.hash;
722 641 : memcpy(encryptionKey, key.encryption_key, sizeof(encryptionKey));
723 : }
724 735 : ReturnErrorOnFailure(writer.Put(TagStartTime(), static_cast<uint64_t>(startTime)));
725 735 : ReturnErrorOnFailure(writer.Put(TagKeyHash(), hash));
726 735 : ReturnErrorOnFailure(writer.Put(TagKeyValue(), ByteSpan(encryptionKey)));
727 :
728 735 : ReturnErrorOnFailure(writer.EndContainer(item));
729 : }
730 245 : ReturnErrorOnFailure(writer.EndContainer(array));
731 : }
732 : // next keyset
733 245 : ReturnErrorOnFailure(writer.Put(TagNext(), static_cast<uint16_t>(next)));
734 :
735 245 : return writer.EndContainer(container);
736 : }
737 :
738 510 : CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
739 : {
740 510 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
741 510 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
742 :
743 : TLV::TLVType container;
744 510 : ReturnErrorOnFailure(reader.EnterContainer(container));
745 :
746 : // policy
747 510 : ReturnErrorOnFailure(reader.Next(TagPolicy()));
748 510 : ReturnErrorOnFailure(reader.Get(policy));
749 : // keys_count
750 510 : ReturnErrorOnFailure(reader.Next(TagNumKeys()));
751 510 : ReturnErrorOnFailure(reader.Get(keys_count));
752 : // TODO(#21614): Enforce maximum number of 3 keys in a keyset
753 : {
754 : // operational_keys
755 510 : ReturnErrorOnFailure(reader.Next(TagGroupCredentials()));
756 510 : VerifyOrReturnError(TLV::kTLVType_Array == reader.GetType(), CHIP_ERROR_INTERNAL);
757 :
758 : TLV::TLVType array, item;
759 510 : ReturnErrorOnFailure(reader.EnterContainer(array));
760 2040 : for (auto & key : operational_keys)
761 : {
762 1530 : ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
763 1530 : VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);
764 :
765 1530 : ReturnErrorOnFailure(reader.EnterContainer(item));
766 : // start_time
767 1530 : ReturnErrorOnFailure(reader.Next(TagStartTime()));
768 1530 : ReturnErrorOnFailure(reader.Get(key.start_time));
769 : // key hash
770 1530 : ReturnErrorOnFailure(reader.Next(TagKeyHash()));
771 1530 : ReturnErrorOnFailure(reader.Get(key.hash));
772 : // key value
773 1530 : ByteSpan encryption_key;
774 1530 : ReturnErrorOnFailure(reader.Next(TagKeyValue()));
775 1530 : ReturnErrorOnFailure(reader.Get(encryption_key));
776 1530 : VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == encryption_key.size(), CHIP_ERROR_INTERNAL);
777 1530 : memcpy(key.encryption_key, encryption_key.data(), encryption_key.size());
778 : // Re-derive privacy key from encryption key when loading from storage to save on storage size.
779 1530 : MutableByteSpan privacy_key(key.privacy_key);
780 1530 : ReturnErrorOnFailure(Crypto::DeriveGroupPrivacyKey(encryption_key, privacy_key));
781 1530 : ReturnErrorOnFailure(reader.ExitContainer(item));
782 : }
783 510 : ReturnErrorOnFailure(reader.ExitContainer(array));
784 : }
785 : // next keyset
786 510 : ReturnErrorOnFailure(reader.Next(TagNext()));
787 510 : ReturnErrorOnFailure(reader.Get(next));
788 :
789 510 : return reader.ExitContainer(container);
790 : }
791 :
792 438 : bool Find(PersistentStorageDelegate * storage, const FabricData & fabric, size_t target_id)
793 : {
794 438 : uint16_t count = 0;
795 :
796 438 : fabric_index = fabric.fabric_index;
797 438 : keyset_id = fabric.first_keyset;
798 438 : first = true;
799 :
800 739 : while (count++ < fabric.keyset_count)
801 : {
802 968 : if (CHIP_NO_ERROR != Load(storage))
803 : {
804 0 : break;
805 : }
806 :
807 484 : if (keyset_id == target_id)
808 : {
809 : // Target id found
810 183 : return true;
811 : }
812 :
813 301 : first = false;
814 301 : prev = keyset_id;
815 301 : keyset_id = next;
816 : }
817 :
818 255 : return false;
819 : }
820 : };
821 :
822 : //
823 : // General
824 : //
825 :
826 : constexpr size_t GroupDataProvider::GroupInfo::kGroupNameMax;
827 : constexpr size_t GroupDataProviderImpl::kIteratorsMax;
828 :
829 105 : CHIP_ERROR GroupDataProviderImpl::Init()
830 : {
831 105 : if (mStorage == nullptr || mSessionKeystore == nullptr)
832 : {
833 0 : return CHIP_ERROR_INCORRECT_STATE;
834 : }
835 105 : return CHIP_NO_ERROR;
836 : }
837 :
838 101 : void GroupDataProviderImpl::Finish()
839 : {
840 101 : mGroupInfoIterators.ReleaseAll();
841 101 : mGroupKeyIterators.ReleaseAll();
842 101 : mEndpointIterators.ReleaseAll();
843 101 : mKeySetIterators.ReleaseAll();
844 101 : mGroupSessionsIterator.ReleaseAll();
845 101 : mGroupKeyContexPool.ReleaseAll();
846 101 : }
847 :
848 105 : void GroupDataProviderImpl::SetStorageDelegate(PersistentStorageDelegate * storage)
849 : {
850 105 : VerifyOrDie(storage != nullptr);
851 105 : mStorage = storage;
852 105 : }
853 :
854 : //
855 : // Group Info
856 : //
857 :
858 253 : CHIP_ERROR GroupDataProviderImpl::SetGroupInfo(chip::FabricIndex fabric_index, const GroupInfo & info)
859 : {
860 253 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
861 :
862 253 : FabricData fabric(fabric_index);
863 253 : GroupData group;
864 :
865 : // Load fabric data (defaults to zero)
866 253 : CHIP_ERROR err = fabric.Load(mStorage);
867 566 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
868 :
869 253 : if (group.Find(mStorage, fabric, info.group_id))
870 : {
871 : // Existing group_id
872 31 : group.Copy(info);
873 31 : return group.Save(mStorage);
874 : }
875 :
876 : // New group_id
877 222 : group.Copy(info);
878 222 : return SetGroupInfoAt(fabric_index, fabric.group_count, group);
879 253 : }
880 :
881 46 : CHIP_ERROR GroupDataProviderImpl::GetGroupInfo(chip::FabricIndex fabric_index, chip::GroupId group_id, GroupInfo & info)
882 : {
883 46 : FabricData fabric(fabric_index);
884 46 : GroupData group;
885 :
886 46 : ReturnErrorOnFailure(fabric.Load(mStorage));
887 41 : info.count = fabric.group_count;
888 41 : VerifyOrReturnError(group.Find(mStorage, fabric, group_id), CHIP_ERROR_NOT_FOUND);
889 :
890 35 : info.Copy(group);
891 35 : return CHIP_NO_ERROR;
892 46 : }
893 :
894 1 : CHIP_ERROR GroupDataProviderImpl::RemoveGroupInfo(chip::FabricIndex fabric_index, chip::GroupId group_id)
895 : {
896 1 : FabricData fabric(fabric_index);
897 1 : GroupData group;
898 :
899 1 : ReturnErrorOnFailure(fabric.Load(mStorage));
900 1 : VerifyOrReturnError(group.Find(mStorage, fabric, group_id), CHIP_ERROR_NOT_FOUND);
901 :
902 1 : return RemoveGroupInfoAt(fabric_index, group.index);
903 1 : }
904 :
905 263 : CHIP_ERROR GroupDataProviderImpl::SetGroupInfoAt(chip::FabricIndex fabric_index, size_t index, const GroupInfo & info)
906 : {
907 263 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
908 :
909 263 : FabricData fabric(fabric_index);
910 263 : GroupData group;
911 :
912 : // Load fabric, defaults to zero
913 263 : CHIP_ERROR err = fabric.Load(mStorage);
914 596 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
915 :
916 : // If the group exists, the index must match
917 263 : bool found = group.Find(mStorage, fabric, info.group_id);
918 263 : VerifyOrReturnError(!found || (group.index == index), CHIP_ERROR_DUPLICATE_KEY_ID);
919 :
920 259 : group.Copy(info);
921 259 : group.endpoint_count = 0;
922 :
923 259 : if (found)
924 : {
925 : // Update existing entry
926 6 : return group.Save(mStorage);
927 : }
928 253 : if (index < fabric.group_count)
929 : {
930 : // Replace existing entry with a new group
931 1 : GroupData old_group;
932 1 : old_group.Get(mStorage, fabric, index);
933 1 : group.first = old_group.first;
934 1 : group.prev = old_group.prev;
935 1 : group.next = old_group.next;
936 :
937 1 : ReturnErrorOnFailure(RemoveEndpoints(fabric_index, old_group.group_id));
938 1 : ReturnErrorOnFailure(old_group.Delete(mStorage));
939 1 : GroupRemoved(fabric_index, old_group);
940 1 : }
941 : else
942 : {
943 : // Insert last
944 252 : VerifyOrReturnError(fabric.group_count == index, CHIP_ERROR_INVALID_ARGUMENT);
945 251 : VerifyOrReturnError(fabric.group_count < mMaxGroupsPerFabric, CHIP_ERROR_INVALID_LIST_LENGTH);
946 249 : fabric.group_count++;
947 : }
948 :
949 250 : ReturnErrorOnFailure(group.Save(mStorage));
950 :
951 250 : if (group.first)
952 : {
953 : // First group, update fabric
954 93 : fabric.first_group = group.group_id;
955 : }
956 : else
957 : {
958 : // Second to last group, update previous
959 157 : GroupData prev(fabric_index, group.prev);
960 157 : ReturnErrorOnFailure(prev.Load(mStorage));
961 157 : prev.next = group.group_id;
962 157 : ReturnErrorOnFailure(prev.Save(mStorage));
963 157 : }
964 : // Update fabric
965 250 : ReturnErrorOnFailure(fabric.Save(mStorage));
966 250 : GroupAdded(fabric_index, group);
967 250 : return CHIP_NO_ERROR;
968 263 : }
969 :
970 52 : CHIP_ERROR GroupDataProviderImpl::GetGroupInfoAt(chip::FabricIndex fabric_index, size_t index, GroupInfo & info)
971 : {
972 52 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
973 :
974 52 : FabricData fabric(fabric_index);
975 52 : GroupData group;
976 :
977 52 : ReturnErrorOnFailure(fabric.Load(mStorage));
978 44 : VerifyOrReturnError(group.Get(mStorage, fabric, index), CHIP_ERROR_NOT_FOUND);
979 :
980 : // Target group found
981 26 : info.Copy(group);
982 26 : return CHIP_NO_ERROR;
983 52 : }
984 :
985 38 : CHIP_ERROR GroupDataProviderImpl::RemoveGroupInfoAt(chip::FabricIndex fabric_index, size_t index)
986 : {
987 38 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
988 :
989 38 : FabricData fabric(fabric_index);
990 38 : GroupData group;
991 :
992 38 : ReturnErrorOnFailure(fabric.Load(mStorage));
993 38 : VerifyOrReturnError(group.Get(mStorage, fabric, index), CHIP_ERROR_NOT_FOUND);
994 :
995 : // Remove endpoints
996 38 : EndpointData endpoint(fabric_index, group.group_id, group.first_endpoint);
997 38 : size_t count = 0;
998 64 : while (count++ < group.endpoint_count)
999 : {
1000 74 : if (CHIP_NO_ERROR != endpoint.Load(mStorage))
1001 : {
1002 11 : break;
1003 : }
1004 26 : TEMPORARY_RETURN_IGNORED endpoint.Delete(mStorage);
1005 26 : endpoint.endpoint_id = endpoint.next;
1006 : }
1007 :
1008 38 : ReturnErrorOnFailure(group.Delete(mStorage));
1009 38 : if (group.first)
1010 : {
1011 : // Remove first group
1012 19 : fabric.first_group = group.next;
1013 : }
1014 : else
1015 : {
1016 : // Remove intermediate group, update previous
1017 19 : GroupData prev_data(fabric_index, group.prev);
1018 19 : ReturnErrorOnFailure(prev_data.Load(mStorage));
1019 19 : prev_data.next = group.next;
1020 19 : ReturnErrorOnFailure(prev_data.Save(mStorage));
1021 19 : }
1022 38 : if (fabric.group_count > 0)
1023 : {
1024 38 : fabric.group_count--;
1025 : }
1026 : // Update fabric info
1027 38 : ReturnErrorOnFailure(fabric.Save(mStorage));
1028 38 : GroupRemoved(fabric_index, group);
1029 38 : return CHIP_NO_ERROR;
1030 38 : }
1031 :
1032 96 : bool GroupDataProviderImpl::HasEndpoint(chip::FabricIndex fabric_index, chip::GroupId group_id, chip::EndpointId endpoint_id)
1033 : {
1034 96 : VerifyOrReturnError(IsInitialized(), false);
1035 :
1036 96 : FabricData fabric(fabric_index);
1037 96 : GroupData group;
1038 96 : EndpointData endpoint;
1039 :
1040 192 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mStorage), false);
1041 85 : VerifyOrReturnError(group.Find(mStorage, fabric, group_id), false);
1042 77 : return endpoint.Find(mStorage, fabric, group, endpoint_id);
1043 96 : }
1044 :
1045 802 : CHIP_ERROR GroupDataProviderImpl::AddEndpoint(chip::FabricIndex fabric_index, chip::GroupId group_id, chip::EndpointId endpoint_id)
1046 : {
1047 802 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1048 :
1049 802 : FabricData fabric(fabric_index);
1050 802 : GroupData group;
1051 :
1052 : // Load fabric data (defaults to zero)
1053 802 : CHIP_ERROR err = fabric.Load(mStorage);
1054 1608 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
1055 :
1056 802 : if (!group.Find(mStorage, fabric, group_id))
1057 : {
1058 : // New group
1059 9 : VerifyOrReturnError(fabric.group_count < mMaxGroupsPerFabric, CHIP_ERROR_INVALID_LIST_LENGTH);
1060 9 : ReturnErrorOnFailure(EndpointData(fabric_index, group_id, endpoint_id).Save(mStorage));
1061 : // Save the new group into the fabric
1062 9 : group.group_id = group_id;
1063 9 : group.name[0] = 0;
1064 9 : group.first_endpoint = endpoint_id;
1065 9 : group.endpoint_count = 1;
1066 9 : group.next = fabric.first_group;
1067 9 : group.prev = kUndefinedGroupId;
1068 9 : ReturnErrorOnFailure(group.Save(mStorage));
1069 : // Update fabric
1070 9 : fabric.first_group = group.group_id;
1071 9 : fabric.group_count++;
1072 9 : ReturnErrorOnFailure(fabric.Save(mStorage));
1073 9 : GroupAdded(fabric_index, group);
1074 9 : return CHIP_NO_ERROR;
1075 : }
1076 :
1077 : // Existing group
1078 793 : EndpointData endpoint;
1079 793 : VerifyOrReturnError(!endpoint.Find(mStorage, fabric, group, endpoint_id), CHIP_NO_ERROR);
1080 :
1081 : // New endpoint, insert last
1082 790 : endpoint.endpoint_id = endpoint_id;
1083 790 : ReturnErrorOnFailure(endpoint.Save(mStorage));
1084 790 : if (endpoint.first)
1085 : {
1086 : // First endpoint of group
1087 224 : group.first_endpoint = endpoint.endpoint_id;
1088 : }
1089 : else
1090 : {
1091 : // Previous endpoint(s)
1092 566 : ReturnErrorOnFailure(endpoint.Save(mStorage));
1093 566 : EndpointData prev(fabric_index, group.group_id, endpoint.prev);
1094 566 : ReturnErrorOnFailure(prev.Load(mStorage));
1095 566 : prev.next = endpoint.endpoint_id;
1096 566 : ReturnErrorOnFailure(prev.Save(mStorage));
1097 566 : }
1098 790 : group.endpoint_count++;
1099 790 : return group.Save(mStorage);
1100 802 : }
1101 :
1102 42 : CHIP_ERROR GroupDataProviderImpl::RemoveEndpoint(chip::FabricIndex fabric_index, chip::GroupId group_id,
1103 : chip::EndpointId endpoint_id)
1104 : {
1105 42 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1106 :
1107 42 : FabricData fabric(fabric_index);
1108 42 : GroupData group;
1109 42 : EndpointData endpoint;
1110 :
1111 42 : ReturnErrorOnFailure(fabric.Load(mStorage));
1112 42 : VerifyOrReturnError(group.Find(mStorage, fabric, group_id), CHIP_ERROR_NOT_FOUND);
1113 41 : VerifyOrReturnError(endpoint.Find(mStorage, fabric, group, endpoint_id), CHIP_ERROR_NOT_FOUND);
1114 :
1115 : // Existing endpoint
1116 40 : TEMPORARY_RETURN_IGNORED endpoint.Delete(mStorage);
1117 :
1118 40 : if (endpoint.first)
1119 : {
1120 : // Remove first
1121 14 : group.first_endpoint = endpoint.next;
1122 : }
1123 : else
1124 : {
1125 : // Remove middle
1126 26 : EndpointData prev(fabric_index, group.group_id, endpoint.prev);
1127 26 : ReturnErrorOnFailure(prev.Load(mStorage));
1128 26 : prev.next = endpoint.next;
1129 26 : ReturnErrorOnFailure(prev.Save(mStorage));
1130 26 : }
1131 :
1132 40 : if (group.endpoint_count > 1)
1133 : {
1134 29 : group.endpoint_count--;
1135 29 : return group.Save(mStorage);
1136 : }
1137 :
1138 : // No more endpoints, remove the group
1139 11 : return RemoveGroupInfoAt(fabric_index, group.index);
1140 42 : }
1141 :
1142 4 : CHIP_ERROR GroupDataProviderImpl::RemoveEndpoint(chip::FabricIndex fabric_index, chip::EndpointId endpoint_id)
1143 : {
1144 4 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1145 :
1146 4 : FabricData fabric(fabric_index);
1147 :
1148 4 : ReturnErrorOnFailure(fabric.Load(mStorage));
1149 :
1150 3 : GroupData group(fabric_index, fabric.first_group);
1151 3 : size_t group_index = 0;
1152 3 : EndpointData endpoint;
1153 :
1154 : // Loop through all the groups
1155 11 : while (group_index < fabric.group_count)
1156 : {
1157 16 : if (CHIP_NO_ERROR != group.Load(mStorage))
1158 : {
1159 0 : break;
1160 : }
1161 8 : if (endpoint.Find(mStorage, fabric, group, endpoint_id))
1162 : {
1163 : // Endpoint found in group
1164 8 : ReturnErrorOnFailure(RemoveEndpoint(fabric_index, group.group_id, endpoint_id));
1165 : }
1166 :
1167 8 : group.group_id = group.next;
1168 8 : group_index++;
1169 : }
1170 :
1171 3 : return CHIP_NO_ERROR;
1172 4 : }
1173 :
1174 17 : GroupDataProvider::GroupInfoIterator * GroupDataProviderImpl::IterateGroupInfo(chip::FabricIndex fabric_index)
1175 : {
1176 17 : VerifyOrReturnError(IsInitialized(), nullptr);
1177 17 : return mGroupInfoIterators.CreateObject(*this, fabric_index);
1178 : }
1179 :
1180 17 : GroupDataProviderImpl::GroupInfoIteratorImpl::GroupInfoIteratorImpl(GroupDataProviderImpl & provider,
1181 17 : chip::FabricIndex fabric_index) :
1182 17 : mProvider(provider),
1183 17 : mFabric(fabric_index)
1184 : {
1185 17 : FabricData fabric(fabric_index);
1186 34 : if (CHIP_NO_ERROR == fabric.Load(provider.mStorage))
1187 : {
1188 16 : mNextId = fabric.first_group;
1189 16 : mTotal = fabric.group_count;
1190 16 : mCount = 0;
1191 : }
1192 17 : }
1193 :
1194 4 : size_t GroupDataProviderImpl::GroupInfoIteratorImpl::Count()
1195 : {
1196 4 : return mTotal;
1197 : }
1198 :
1199 40 : bool GroupDataProviderImpl::GroupInfoIteratorImpl::Next(GroupInfo & output)
1200 : {
1201 40 : VerifyOrReturnError(mCount < mTotal, false);
1202 :
1203 26 : GroupData group(mFabric, mNextId);
1204 26 : CHIP_ERROR err = group.Load(mProvider.mStorage);
1205 52 : VerifyOrReturnError(CHIP_NO_ERROR == err, false);
1206 :
1207 26 : mCount++;
1208 26 : mNextId = group.next;
1209 26 : output.Copy(group);
1210 26 : return true;
1211 26 : }
1212 :
1213 17 : void GroupDataProviderImpl::GroupInfoIteratorImpl::Release()
1214 : {
1215 17 : mProvider.mGroupInfoIterators.ReleaseObject(this);
1216 17 : }
1217 :
1218 31 : GroupDataProvider::EndpointIterator * GroupDataProviderImpl::IterateEndpoints(chip::FabricIndex fabric_index,
1219 : std::optional<GroupId> group_id)
1220 : {
1221 31 : VerifyOrReturnError(IsInitialized(), nullptr);
1222 31 : return mEndpointIterators.CreateObject(*this, fabric_index, group_id);
1223 : }
1224 :
1225 31 : GroupDataProviderImpl::EndpointIteratorImpl::EndpointIteratorImpl(GroupDataProviderImpl & provider, chip::FabricIndex fabric_index,
1226 31 : std::optional<GroupId> group_id) :
1227 31 : mProvider(provider),
1228 31 : mFabric(fabric_index)
1229 : {
1230 31 : FabricData fabric(fabric_index);
1231 62 : VerifyOrReturn(CHIP_NO_ERROR == fabric.Load(provider.mStorage));
1232 :
1233 29 : if (group_id.has_value())
1234 : {
1235 19 : GroupData group(fabric_index, *group_id);
1236 38 : VerifyOrReturn(CHIP_NO_ERROR == group.Load(provider.mStorage));
1237 :
1238 18 : mGroup = *group_id;
1239 18 : mFirstGroup = *group_id;
1240 18 : mGroupCount = 1;
1241 18 : mEndpoint = group.first_endpoint;
1242 18 : mEndpointCount = group.endpoint_count;
1243 19 : }
1244 : else
1245 : {
1246 10 : GroupData group(fabric_index, fabric.first_group);
1247 20 : VerifyOrReturn(CHIP_NO_ERROR == group.Load(provider.mStorage));
1248 :
1249 10 : mGroup = fabric.first_group;
1250 10 : mFirstGroup = fabric.first_group;
1251 10 : mGroupCount = fabric.group_count;
1252 10 : mEndpoint = group.first_endpoint;
1253 10 : mEndpointCount = group.endpoint_count;
1254 10 : }
1255 31 : }
1256 :
1257 24 : size_t GroupDataProviderImpl::EndpointIteratorImpl::Count()
1258 : {
1259 24 : GroupData group(mFabric, mFirstGroup);
1260 24 : size_t group_index = 0;
1261 24 : size_t endpoint_index = 0;
1262 24 : size_t count = 0;
1263 :
1264 48 : while (group_index++ < mGroupCount)
1265 : {
1266 48 : if (CHIP_NO_ERROR != group.Load(mProvider.mStorage))
1267 : {
1268 0 : break;
1269 : }
1270 24 : EndpointData endpoint(mFabric, group.group_id, group.first_endpoint);
1271 965 : while (endpoint_index++ < group.endpoint_count)
1272 : {
1273 1882 : if (CHIP_NO_ERROR != endpoint.Load(mProvider.mStorage))
1274 : {
1275 0 : break;
1276 : }
1277 941 : endpoint.endpoint_id = endpoint.next;
1278 941 : count++;
1279 : }
1280 24 : group.group_id = group.next;
1281 24 : endpoint_index = 0;
1282 24 : }
1283 48 : return count;
1284 24 : }
1285 :
1286 970 : bool GroupDataProviderImpl::EndpointIteratorImpl::Next(GroupEndpoint & output)
1287 : {
1288 1006 : while (mGroupIndex < mGroupCount)
1289 : {
1290 980 : GroupData group(mFabric, mGroup);
1291 1960 : if (CHIP_NO_ERROR != group.Load(mProvider.mStorage))
1292 : {
1293 0 : mGroupIndex = mGroupCount;
1294 0 : return false;
1295 : }
1296 980 : if (mFirstEndpoint)
1297 : {
1298 36 : mEndpoint = group.first_endpoint;
1299 36 : mEndpointIndex = 0;
1300 36 : mEndpointCount = group.endpoint_count;
1301 36 : mFirstEndpoint = false;
1302 : }
1303 980 : if (mEndpointIndex < mEndpointCount)
1304 : {
1305 944 : EndpointData endpoint(mFabric, mGroup, mEndpoint);
1306 1888 : if (CHIP_NO_ERROR == endpoint.Load(mProvider.mStorage))
1307 : {
1308 944 : output.group_id = group.group_id;
1309 944 : output.endpoint_id = endpoint.endpoint_id;
1310 944 : mEndpoint = endpoint.next;
1311 944 : mEndpointIndex++;
1312 944 : return true;
1313 : }
1314 944 : }
1315 36 : mGroup = group.next;
1316 36 : mGroupIndex++;
1317 36 : mFirstEndpoint = true;
1318 980 : }
1319 26 : return false;
1320 : }
1321 :
1322 31 : void GroupDataProviderImpl::EndpointIteratorImpl::Release()
1323 : {
1324 31 : mProvider.mEndpointIterators.ReleaseObject(this);
1325 31 : }
1326 :
1327 1 : CHIP_ERROR GroupDataProviderImpl::RemoveEndpoints(chip::FabricIndex fabric_index, chip::GroupId group_id)
1328 : {
1329 1 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1330 :
1331 1 : FabricData fabric(fabric_index);
1332 1 : GroupData group;
1333 :
1334 2 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mStorage), CHIP_ERROR_INVALID_FABRIC_INDEX);
1335 1 : VerifyOrReturnError(group.Find(mStorage, fabric, group_id), CHIP_ERROR_KEY_NOT_FOUND);
1336 :
1337 1 : EndpointData endpoint(fabric_index, group.group_id, group.first_endpoint);
1338 1 : size_t endpoint_index = 0;
1339 1 : while (endpoint_index < group.endpoint_count)
1340 : {
1341 0 : ReturnErrorOnFailure(endpoint.Load(mStorage));
1342 0 : TEMPORARY_RETURN_IGNORED endpoint.Delete(mStorage);
1343 0 : endpoint.endpoint_id = endpoint.next;
1344 0 : endpoint_index++;
1345 : }
1346 1 : group.first_endpoint = kInvalidEndpointId;
1347 1 : group.endpoint_count = 0;
1348 1 : ReturnErrorOnFailure(group.Save(mStorage));
1349 :
1350 1 : return CHIP_NO_ERROR;
1351 1 : }
1352 :
1353 : //
1354 : // Group-Key map
1355 : //
1356 :
1357 36 : CHIP_ERROR GroupDataProviderImpl::SetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId keyset_id)
1358 : {
1359 36 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1360 :
1361 36 : FabricData fabric(fabric_index);
1362 36 : ReturnErrorOnFailure(fabric.Load(mStorage));
1363 :
1364 : // Search for an existing mapping
1365 36 : size_t count = 0;
1366 36 : KeyMapData map(fabric_index, fabric.first_map);
1367 48 : while (count++ < fabric.map_count)
1368 : {
1369 39 : ReturnErrorOnFailure(map.Load(mStorage));
1370 39 : if (map.group_id == group_id)
1371 : {
1372 : // Existing group, replace keyset
1373 27 : map.keyset_id = keyset_id;
1374 27 : return map.Save(mStorage);
1375 : }
1376 12 : map.id = map.next;
1377 : }
1378 :
1379 : // New group, insert last
1380 9 : GroupKey entry(group_id, keyset_id);
1381 9 : return SetGroupKeyAt(fabric_index, fabric.map_count, entry);
1382 36 : }
1383 :
1384 264 : CHIP_ERROR GroupDataProviderImpl::SetGroupKeyAt(chip::FabricIndex fabric_index, size_t index, const GroupKey & in_map)
1385 : {
1386 264 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1387 :
1388 264 : FabricData fabric(fabric_index);
1389 264 : KeyMapData map(fabric_index);
1390 :
1391 : // Load fabric, defaults to zero
1392 264 : CHIP_ERROR err = fabric.Load(mStorage);
1393 536 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
1394 :
1395 : // If the group exists, the index must match
1396 264 : bool found = map.Find(mStorage, fabric, in_map);
1397 264 : VerifyOrReturnError(!found || (map.index == index), CHIP_ERROR_DUPLICATE_KEY_ID);
1398 :
1399 259 : found = map.Get(mStorage, fabric, index);
1400 259 : map.group_id = in_map.group_id;
1401 259 : map.keyset_id = in_map.keyset_id;
1402 :
1403 259 : if (found)
1404 : {
1405 : // Update existing map
1406 8 : return map.Save(mStorage);
1407 : }
1408 :
1409 : // Insert last
1410 251 : VerifyOrReturnError(fabric.map_count == index, CHIP_ERROR_INVALID_ARGUMENT);
1411 250 : VerifyOrReturnError(fabric.map_count < mMaxGroupsPerFabric, CHIP_ERROR_INVALID_LIST_LENGTH);
1412 :
1413 249 : map.next = 0;
1414 249 : ReturnErrorOnFailure(map.Save(mStorage));
1415 :
1416 249 : if (map.first)
1417 : {
1418 : // First map, update fabric
1419 92 : fabric.first_map = map.id;
1420 : }
1421 : else
1422 : {
1423 : // Last map, update previous
1424 157 : KeyMapData prev(fabric_index, map.prev);
1425 157 : ReturnErrorOnFailure(prev.Load(mStorage));
1426 157 : prev.next = map.id;
1427 157 : ReturnErrorOnFailure(prev.Save(mStorage));
1428 157 : }
1429 : // Update fabric
1430 249 : fabric.map_count++;
1431 249 : return fabric.Save(mStorage);
1432 264 : }
1433 :
1434 16 : CHIP_ERROR GroupDataProviderImpl::GetGroupKey(FabricIndex fabric_index, GroupId group_id, KeysetId & keyset_id)
1435 : {
1436 16 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1437 :
1438 16 : FabricData fabric(fabric_index);
1439 16 : ReturnErrorOnFailure(fabric.Load(mStorage));
1440 :
1441 16 : size_t count = 0;
1442 16 : KeyMapData map(fabric_index, fabric.first_map);
1443 22 : while (count++ < fabric.map_count)
1444 : {
1445 22 : ReturnErrorOnFailure(map.Load(mStorage));
1446 22 : if (map.group_id == group_id)
1447 : {
1448 16 : keyset_id = map.keyset_id;
1449 16 : return CHIP_NO_ERROR;
1450 : }
1451 6 : map.id = map.next;
1452 : }
1453 0 : return CHIP_ERROR_NOT_FOUND;
1454 16 : }
1455 :
1456 28 : CHIP_ERROR GroupDataProviderImpl::GetGroupKeyAt(chip::FabricIndex fabric_index, size_t index, GroupKey & out_map)
1457 : {
1458 28 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1459 :
1460 28 : FabricData fabric(fabric_index);
1461 28 : KeyMapData map;
1462 :
1463 28 : ReturnErrorOnFailure(fabric.Load(mStorage));
1464 27 : VerifyOrReturnError(map.Get(mStorage, fabric, index), CHIP_ERROR_NOT_FOUND);
1465 :
1466 : // Target map found
1467 19 : out_map.group_id = map.group_id;
1468 19 : out_map.keyset_id = map.keyset_id;
1469 19 : return CHIP_NO_ERROR;
1470 28 : }
1471 :
1472 14 : CHIP_ERROR GroupDataProviderImpl::RemoveGroupKeyAt(chip::FabricIndex fabric_index, size_t index)
1473 : {
1474 14 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1475 :
1476 14 : FabricData fabric(fabric_index);
1477 14 : KeyMapData map;
1478 :
1479 14 : ReturnErrorOnFailure(fabric.Load(mStorage));
1480 14 : VerifyOrReturnError(map.Get(mStorage, fabric, index), CHIP_ERROR_NOT_FOUND);
1481 :
1482 14 : ReturnErrorOnFailure(map.Delete(mStorage));
1483 14 : if (map.first)
1484 : {
1485 : // Remove first map
1486 4 : fabric.first_map = map.next;
1487 : }
1488 : else
1489 : {
1490 : // Remove intermediate map, update previous
1491 10 : KeyMapData prev_data(fabric_index, map.prev);
1492 10 : ReturnErrorOnFailure(prev_data.Load(mStorage));
1493 10 : prev_data.next = map.next;
1494 10 : ReturnErrorOnFailure(prev_data.Save(mStorage));
1495 10 : }
1496 14 : if (fabric.map_count > 0)
1497 : {
1498 14 : fabric.map_count--;
1499 : }
1500 : // Update fabric
1501 14 : return fabric.Save(mStorage);
1502 14 : }
1503 :
1504 4 : CHIP_ERROR GroupDataProviderImpl::RemoveGroupKeys(chip::FabricIndex fabric_index)
1505 : {
1506 4 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1507 :
1508 4 : FabricData fabric(fabric_index);
1509 8 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mStorage), CHIP_ERROR_INVALID_FABRIC_INDEX);
1510 :
1511 1 : size_t count = 0;
1512 1 : KeyMapData map(fabric_index, fabric.first_map);
1513 4 : while (count++ < fabric.map_count)
1514 : {
1515 6 : if (CHIP_NO_ERROR != map.Load(mStorage))
1516 : {
1517 0 : break;
1518 : }
1519 3 : TEMPORARY_RETURN_IGNORED map.Delete(mStorage);
1520 3 : map.id = map.next;
1521 : }
1522 :
1523 : // Update fabric
1524 1 : fabric.first_map = 0;
1525 1 : fabric.map_count = 0;
1526 1 : return fabric.Save(mStorage);
1527 4 : }
1528 :
1529 39 : GroupDataProvider::GroupKeyIterator * GroupDataProviderImpl::IterateGroupKeys(chip::FabricIndex fabric_index)
1530 : {
1531 39 : VerifyOrReturnError(IsInitialized(), nullptr);
1532 39 : return mGroupKeyIterators.CreateObject(*this, fabric_index);
1533 : }
1534 :
1535 39 : GroupDataProviderImpl::GroupKeyIteratorImpl::GroupKeyIteratorImpl(GroupDataProviderImpl & provider,
1536 39 : chip::FabricIndex fabric_index) :
1537 39 : mProvider(provider),
1538 39 : mFabric(fabric_index)
1539 : {
1540 39 : FabricData fabric(fabric_index);
1541 78 : if (CHIP_NO_ERROR == fabric.Load(provider.mStorage))
1542 : {
1543 37 : mNextId = fabric.first_map;
1544 37 : mTotal = fabric.map_count;
1545 37 : mCount = 0;
1546 : }
1547 39 : }
1548 :
1549 7 : size_t GroupDataProviderImpl::GroupKeyIteratorImpl::Count()
1550 : {
1551 7 : return mTotal;
1552 : }
1553 :
1554 74 : bool GroupDataProviderImpl::GroupKeyIteratorImpl::Next(GroupKey & output)
1555 : {
1556 74 : VerifyOrReturnError(mCount < mTotal, false);
1557 :
1558 66 : KeyMapData map(mFabric, mNextId);
1559 132 : VerifyOrReturnError(CHIP_NO_ERROR == map.Load(mProvider.mStorage), false);
1560 :
1561 66 : mCount++;
1562 66 : mNextId = map.next;
1563 66 : output.group_id = map.group_id;
1564 66 : output.keyset_id = map.keyset_id;
1565 66 : return true;
1566 66 : }
1567 :
1568 39 : void GroupDataProviderImpl::GroupKeyIteratorImpl::Release()
1569 : {
1570 39 : mProvider.mGroupKeyIterators.ReleaseObject(this);
1571 39 : }
1572 :
1573 : //
1574 : // Key Sets
1575 : //
1576 :
1577 : constexpr size_t GroupDataProvider::EpochKey::kLengthBytes;
1578 :
1579 242 : CHIP_ERROR GroupDataProviderImpl::SetKeySet(chip::FabricIndex fabric_index, const ByteSpan & compressed_fabric_id,
1580 : const KeySet & in_keyset)
1581 : {
1582 242 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1583 :
1584 242 : FabricData fabric(fabric_index);
1585 242 : KeySetData keyset;
1586 :
1587 : // Load fabric, defaults to zero
1588 242 : CHIP_ERROR err = fabric.Load(mStorage);
1589 516 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
1590 :
1591 : // Search existing keyset
1592 242 : bool found = keyset.Find(mStorage, fabric, in_keyset.keyset_id);
1593 :
1594 242 : keyset.keyset_id = in_keyset.keyset_id;
1595 242 : keyset.policy = in_keyset.policy;
1596 242 : keyset.keys_count = in_keyset.num_keys_used;
1597 242 : memset(keyset.operational_keys, 0x00, sizeof(keyset.operational_keys));
1598 242 : keyset.operational_keys[0].start_time = in_keyset.epoch_keys[0].start_time;
1599 242 : keyset.operational_keys[1].start_time = in_keyset.epoch_keys[1].start_time;
1600 242 : keyset.operational_keys[2].start_time = in_keyset.epoch_keys[2].start_time;
1601 :
1602 : // Store the operational keys and hash instead of the epoch keys
1603 875 : for (size_t i = 0; i < in_keyset.num_keys_used; ++i)
1604 : {
1605 633 : ByteSpan epoch_key(in_keyset.epoch_keys[i].key, Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);
1606 633 : ReturnErrorOnFailure(
1607 : Crypto::DeriveGroupOperationalCredentials(epoch_key, compressed_fabric_id, keyset.operational_keys[i]));
1608 : }
1609 :
1610 242 : if (found)
1611 : {
1612 : // Update existing keyset info, keep next
1613 5 : return keyset.Save(mStorage);
1614 : }
1615 :
1616 : // New keyset
1617 237 : VerifyOrReturnError(fabric.keyset_count < mMaxGroupKeysPerFabric, CHIP_ERROR_INVALID_LIST_LENGTH);
1618 :
1619 : // Insert first
1620 236 : keyset.next = fabric.first_keyset;
1621 236 : ReturnErrorOnFailure(keyset.Save(mStorage));
1622 : // Update fabric
1623 236 : fabric.keyset_count++;
1624 236 : fabric.first_keyset = in_keyset.keyset_id;
1625 236 : return fabric.Save(mStorage);
1626 242 : }
1627 :
1628 105 : CHIP_ERROR GroupDataProviderImpl::GetKeySet(chip::FabricIndex fabric_index, uint16_t target_id, KeySet & out_keyset)
1629 : {
1630 105 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1631 :
1632 105 : FabricData fabric(fabric_index);
1633 105 : KeySetData keyset;
1634 :
1635 105 : ReturnErrorOnFailure(fabric.Load(mStorage));
1636 97 : VerifyOrReturnError(keyset.Find(mStorage, fabric, target_id), CHIP_ERROR_NOT_FOUND);
1637 :
1638 : // Target keyset found
1639 85 : out_keyset.ClearKeys();
1640 85 : out_keyset.keyset_id = keyset.keyset_id;
1641 85 : out_keyset.policy = keyset.policy;
1642 85 : out_keyset.num_keys_used = keyset.keys_count;
1643 : // Epoch keys are not read back, only start times
1644 85 : out_keyset.epoch_keys[0].start_time = keyset.operational_keys[0].start_time;
1645 85 : out_keyset.epoch_keys[1].start_time = keyset.operational_keys[1].start_time;
1646 85 : out_keyset.epoch_keys[2].start_time = keyset.operational_keys[2].start_time;
1647 :
1648 85 : return CHIP_NO_ERROR;
1649 105 : }
1650 :
1651 28 : CHIP_ERROR GroupDataProviderImpl::RemoveKeySet(chip::FabricIndex fabric_index, uint16_t target_id)
1652 : {
1653 28 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
1654 :
1655 28 : FabricData fabric(fabric_index);
1656 28 : KeySetData keyset;
1657 :
1658 28 : ReturnErrorOnFailure(fabric.Load(mStorage));
1659 28 : VerifyOrReturnError(keyset.Find(mStorage, fabric, target_id), CHIP_ERROR_NOT_FOUND);
1660 24 : ReturnErrorOnFailure(keyset.Delete(mStorage));
1661 :
1662 24 : if (keyset.first)
1663 : {
1664 : // Remove first keyset
1665 20 : fabric.first_keyset = keyset.next;
1666 : }
1667 : else
1668 : {
1669 : // Remove intermediate keyset, update previous
1670 4 : KeySetData prev_data(fabric_index, keyset.prev);
1671 4 : ReturnErrorOnFailure(prev_data.Load(mStorage));
1672 4 : prev_data.next = keyset.next;
1673 4 : ReturnErrorOnFailure(prev_data.Save(mStorage));
1674 4 : }
1675 24 : if (fabric.keyset_count > 0)
1676 : {
1677 24 : fabric.keyset_count--;
1678 : }
1679 : // Update fabric info
1680 24 : ReturnErrorOnFailure(fabric.Save(mStorage));
1681 :
1682 : // Removing a key set also removes the associated group mappings
1683 24 : KeyMapData map;
1684 24 : uint16_t original_count = fabric.map_count;
1685 24 : for (uint16_t i = 0; i < original_count; ++i)
1686 : {
1687 0 : TEMPORARY_RETURN_IGNORED fabric.Load(mStorage);
1688 0 : size_t idx = map.Find(mStorage, fabric, target_id);
1689 0 : if (idx == std::numeric_limits<size_t>::max())
1690 : {
1691 0 : break;
1692 : }
1693 : // NOTE: It's unclear what should happen here if we have removed the key set
1694 : // and possibly some mappings before failing. For now, ignoring errors, but
1695 : // open to suggestsions for the correct behavior.
1696 0 : TEMPORARY_RETURN_IGNORED RemoveGroupKeyAt(fabric_index, idx);
1697 : }
1698 24 : return CHIP_NO_ERROR;
1699 28 : }
1700 :
1701 2 : GroupDataProvider::KeySetIterator * GroupDataProviderImpl::IterateKeySets(chip::FabricIndex fabric_index)
1702 : {
1703 2 : VerifyOrReturnError(IsInitialized(), nullptr);
1704 2 : return mKeySetIterators.CreateObject(*this, fabric_index);
1705 : }
1706 :
1707 2 : GroupDataProviderImpl::KeySetIteratorImpl::KeySetIteratorImpl(GroupDataProviderImpl & provider, chip::FabricIndex fabric_index) :
1708 2 : mProvider(provider), mFabric(fabric_index)
1709 : {
1710 2 : FabricData fabric(fabric_index);
1711 4 : if (CHIP_NO_ERROR == fabric.Load(provider.mStorage))
1712 : {
1713 2 : mNextId = fabric.first_keyset;
1714 2 : mTotal = fabric.keyset_count;
1715 2 : mCount = 0;
1716 : }
1717 2 : }
1718 :
1719 2 : size_t GroupDataProviderImpl::KeySetIteratorImpl::Count()
1720 : {
1721 2 : return mTotal;
1722 : }
1723 :
1724 9 : bool GroupDataProviderImpl::KeySetIteratorImpl::Next(KeySet & output)
1725 : {
1726 9 : VerifyOrReturnError(mCount < mTotal, false);
1727 :
1728 7 : KeySetData keyset(mFabric, mNextId);
1729 14 : VerifyOrReturnError(CHIP_NO_ERROR == keyset.Load(mProvider.mStorage), false);
1730 :
1731 7 : mCount++;
1732 7 : mNextId = keyset.next;
1733 7 : output.ClearKeys();
1734 7 : output.keyset_id = keyset.keyset_id;
1735 7 : output.policy = keyset.policy;
1736 7 : output.num_keys_used = keyset.keys_count;
1737 : // Epoch keys are not read back, only start times
1738 7 : output.epoch_keys[0].start_time = keyset.operational_keys[0].start_time;
1739 7 : output.epoch_keys[1].start_time = keyset.operational_keys[1].start_time;
1740 7 : output.epoch_keys[2].start_time = keyset.operational_keys[2].start_time;
1741 7 : return true;
1742 7 : }
1743 :
1744 2 : void GroupDataProviderImpl::KeySetIteratorImpl::Release()
1745 : {
1746 2 : mProvider.mKeySetIterators.ReleaseObject(this);
1747 2 : }
1748 :
1749 : //
1750 : // Fabrics
1751 : //
1752 :
1753 23 : CHIP_ERROR GroupDataProviderImpl::RemoveFabric(chip::FabricIndex fabric_index)
1754 : {
1755 23 : FabricData fabric(fabric_index);
1756 :
1757 : // Fabric data defaults to zero, so if not entry is found, no mappings, or keys are removed
1758 : // However, states has a separate list, and needs to be removed regardless
1759 23 : CHIP_ERROR err = fabric.Load(mStorage);
1760 50 : VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
1761 :
1762 : // Remove Group mappings
1763 :
1764 35 : for (size_t i = 0; i < fabric.map_count; i++)
1765 : {
1766 12 : TEMPORARY_RETURN_IGNORED RemoveGroupKeyAt(fabric_index, fabric.map_count - i - 1);
1767 : }
1768 :
1769 : // Remove group info
1770 :
1771 48 : for (size_t i = 0; i < fabric.group_count; i++)
1772 : {
1773 25 : TEMPORARY_RETURN_IGNORED RemoveGroupInfoAt(fabric_index, fabric.group_count - i - 1);
1774 : }
1775 :
1776 : // Remove Keysets
1777 :
1778 23 : KeySetData keyset(fabric_index, fabric.first_keyset);
1779 23 : size_t keyset_count = 0;
1780 :
1781 : // Loop the keysets associated with the target fabric
1782 38 : while (keyset_count < fabric.keyset_count)
1783 : {
1784 30 : if (CHIP_NO_ERROR != keyset.Load(mStorage))
1785 : {
1786 0 : break;
1787 : }
1788 15 : TEMPORARY_RETURN_IGNORED RemoveKeySet(fabric_index, keyset.keyset_id);
1789 15 : keyset.keyset_id = keyset.next;
1790 15 : keyset_count++;
1791 : }
1792 :
1793 : // Remove fabric
1794 23 : return fabric.Delete(mStorage);
1795 23 : }
1796 :
1797 : //
1798 : // Cryptography
1799 : //
1800 :
1801 4 : Crypto::SymmetricKeyContext * GroupDataProviderImpl::GetKeyContext(FabricIndex fabric_index, GroupId group_id)
1802 : {
1803 4 : FabricData fabric(fabric_index);
1804 8 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mStorage), nullptr);
1805 :
1806 4 : KeyMapData mapping(fabric.fabric_index, fabric.first_map);
1807 :
1808 : // Look for the target group in the fabric's keyset-group pairs
1809 4 : for (uint16_t i = 0; i < fabric.map_count; ++i, mapping.id = mapping.next)
1810 : {
1811 8 : VerifyOrReturnError(CHIP_NO_ERROR == mapping.Load(mStorage), nullptr);
1812 : // GroupKeySetID of 0 is reserved for the Identity Protection Key (IPK),
1813 : // it cannot be used for operational group communication.
1814 4 : if (mapping.keyset_id > 0 && mapping.group_id == group_id)
1815 : {
1816 : // Group found, get the keyset
1817 4 : KeySetData keyset;
1818 4 : VerifyOrReturnError(keyset.Find(mStorage, fabric, mapping.keyset_id), nullptr);
1819 4 : Crypto::GroupOperationalCredentials * creds = keyset.GetCurrentGroupCredentials();
1820 4 : if (nullptr != creds)
1821 : {
1822 4 : return mGroupKeyContexPool.CreateObject(*this, creds->encryption_key, creds->hash, creds->privacy_key);
1823 : }
1824 4 : }
1825 : }
1826 0 : return nullptr;
1827 4 : }
1828 :
1829 30 : CHIP_ERROR GroupDataProviderImpl::GetIpkKeySet(FabricIndex fabric_index, KeySet & out_keyset)
1830 : {
1831 30 : FabricData fabric(fabric_index);
1832 60 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mStorage), CHIP_ERROR_NOT_FOUND);
1833 :
1834 29 : KeyMapData mapping(fabric.fabric_index, fabric.first_map);
1835 :
1836 : // Fabric found, get the keyset
1837 29 : KeySetData keyset;
1838 29 : VerifyOrReturnError(keyset.Find(mStorage, fabric, kIdentityProtectionKeySetId), CHIP_ERROR_NOT_FOUND);
1839 :
1840 : // If the keyset ID doesn't match, we have a ... problem.
1841 27 : VerifyOrReturnError(keyset.keyset_id == kIdentityProtectionKeySetId, CHIP_ERROR_INTERNAL);
1842 :
1843 27 : out_keyset.keyset_id = keyset.keyset_id;
1844 27 : out_keyset.num_keys_used = keyset.keys_count;
1845 27 : out_keyset.policy = keyset.policy;
1846 :
1847 108 : for (size_t key_idx = 0; key_idx < MATTER_ARRAY_SIZE(out_keyset.epoch_keys); ++key_idx)
1848 : {
1849 81 : out_keyset.epoch_keys[key_idx].Clear();
1850 81 : if (key_idx < keyset.keys_count)
1851 : {
1852 27 : out_keyset.epoch_keys[key_idx].start_time = keyset.operational_keys[key_idx].start_time;
1853 27 : memcpy(&out_keyset.epoch_keys[key_idx].key[0], keyset.operational_keys[key_idx].encryption_key, EpochKey::kLengthBytes);
1854 : }
1855 : }
1856 :
1857 27 : return CHIP_NO_ERROR;
1858 30 : }
1859 :
1860 4 : void GroupDataProviderImpl::GroupKeyContext::Release()
1861 : {
1862 4 : ReleaseKeys();
1863 4 : mProvider.mGroupKeyContexPool.ReleaseObject(this);
1864 4 : }
1865 :
1866 4 : CHIP_ERROR GroupDataProviderImpl::GroupKeyContext::MessageEncrypt(const ByteSpan & plaintext, const ByteSpan & aad,
1867 : const ByteSpan & nonce, MutableByteSpan & mic,
1868 : MutableByteSpan & ciphertext) const
1869 : {
1870 4 : uint8_t * output = ciphertext.data();
1871 4 : return Crypto::AES_CCM_encrypt(plaintext.data(), plaintext.size(), aad.data(), aad.size(), mEncryptionKey, nonce.data(),
1872 4 : nonce.size(), output, mic.data(), mic.size());
1873 : }
1874 :
1875 8 : CHIP_ERROR GroupDataProviderImpl::GroupKeyContext::MessageDecrypt(const ByteSpan & ciphertext, const ByteSpan & aad,
1876 : const ByteSpan & nonce, const ByteSpan & mic,
1877 : MutableByteSpan & plaintext) const
1878 : {
1879 8 : uint8_t * output = plaintext.data();
1880 16 : return Crypto::AES_CCM_decrypt(ciphertext.data(), ciphertext.size(), aad.data(), aad.size(), mic.data(), mic.size(),
1881 16 : mEncryptionKey, nonce.data(), nonce.size(), output);
1882 : }
1883 :
1884 0 : CHIP_ERROR GroupDataProviderImpl::GroupKeyContext::PrivacyEncrypt(const ByteSpan & input, const ByteSpan & nonce,
1885 : MutableByteSpan & output) const
1886 : {
1887 0 : return Crypto::AES_CTR_crypt(input.data(), input.size(), mPrivacyKey, nonce.data(), nonce.size(), output.data());
1888 : }
1889 :
1890 3 : CHIP_ERROR GroupDataProviderImpl::GroupKeyContext::PrivacyDecrypt(const ByteSpan & input, const ByteSpan & nonce,
1891 : MutableByteSpan & output) const
1892 : {
1893 3 : return Crypto::AES_CTR_crypt(input.data(), input.size(), mPrivacyKey, nonce.data(), nonce.size(), output.data());
1894 : }
1895 :
1896 9 : GroupDataProviderImpl::GroupSessionIterator * GroupDataProviderImpl::IterateGroupSessions(uint16_t session_id)
1897 : {
1898 9 : VerifyOrReturnError(IsInitialized(), nullptr);
1899 9 : return mGroupSessionsIterator.CreateObject(*this, session_id);
1900 : }
1901 :
1902 9 : GroupDataProviderImpl::GroupSessionIteratorImpl::GroupSessionIteratorImpl(GroupDataProviderImpl & provider, uint16_t session_id) :
1903 9 : mProvider(provider), mSessionId(session_id), mGroupKeyContext(provider)
1904 : {
1905 9 : FabricList fabric_list;
1906 9 : ReturnOnFailure(fabric_list.Load(provider.mStorage));
1907 9 : mFirstFabric = fabric_list.first_entry;
1908 9 : mFabric = fabric_list.first_entry;
1909 9 : mFabricCount = 0;
1910 9 : mFabricTotal = fabric_list.entry_count;
1911 9 : mMapCount = 0;
1912 9 : mFirstMap = true;
1913 9 : }
1914 :
1915 1 : size_t GroupDataProviderImpl::GroupSessionIteratorImpl::Count()
1916 : {
1917 1 : FabricData fabric(mFirstFabric);
1918 1 : size_t count = 0;
1919 :
1920 3 : for (size_t i = 0; i < mFabricTotal; i++, fabric.fabric_index = fabric.next)
1921 : {
1922 4 : if (CHIP_NO_ERROR != fabric.Load(mProvider.mStorage))
1923 : {
1924 0 : break;
1925 : }
1926 :
1927 : // Iterate key sets
1928 2 : KeyMapData mapping(fabric.fabric_index, fabric.first_map);
1929 :
1930 : // Look for the target group in the fabric's keyset-group pairs
1931 8 : for (uint16_t j = 0; j < fabric.map_count; ++j, mapping.id = mapping.next)
1932 : {
1933 12 : if (CHIP_NO_ERROR != mapping.Load(mProvider.mStorage))
1934 : {
1935 0 : break;
1936 : }
1937 :
1938 : // Group found, get the keyset
1939 6 : KeySetData keyset;
1940 6 : if (!keyset.Find(mProvider.mStorage, fabric, mapping.keyset_id))
1941 : {
1942 0 : break;
1943 : }
1944 20 : for (uint16_t k = 0; k < keyset.keys_count; ++k)
1945 : {
1946 14 : if (keyset.operational_keys[k].hash == mSessionId)
1947 : {
1948 1 : count++;
1949 : }
1950 : }
1951 6 : }
1952 2 : }
1953 2 : return count;
1954 1 : }
1955 :
1956 11 : bool GroupDataProviderImpl::GroupSessionIteratorImpl::Next(GroupSession & output)
1957 : {
1958 37 : while (mFabricCount < mFabricTotal)
1959 : {
1960 35 : FabricData fabric(mFabric);
1961 70 : VerifyOrReturnError(CHIP_NO_ERROR == fabric.Load(mProvider.mStorage), false);
1962 :
1963 35 : if (mMapCount >= fabric.map_count)
1964 : {
1965 : // No more keyset/group mappings on the current fabric, try next fabric
1966 3 : mFabric = fabric.next;
1967 3 : mFabricCount++;
1968 3 : mFirstMap = true;
1969 3 : mMapCount = 0;
1970 3 : continue;
1971 : }
1972 :
1973 32 : if (mFirstMap)
1974 : {
1975 10 : mMapping = fabric.first_map;
1976 10 : mFirstMap = false;
1977 : }
1978 :
1979 32 : KeyMapData mapping(mFabric, mMapping);
1980 64 : VerifyOrReturnError(CHIP_NO_ERROR == mapping.Load(mProvider.mStorage), false);
1981 :
1982 : // Group found, get the keyset
1983 32 : KeySetData keyset;
1984 32 : VerifyOrReturnError(keyset.Find(mProvider.mStorage, fabric, mapping.keyset_id), false);
1985 :
1986 32 : if (mKeyIndex >= keyset.keys_count || (mKeyIndex >= KeySet::kEpochKeysMax))
1987 : {
1988 : // No more keys in current keyset, try next
1989 7 : mMapping = mapping.next;
1990 7 : mMapCount++;
1991 7 : mKeyIndex = 0;
1992 7 : continue;
1993 : }
1994 :
1995 25 : Crypto::GroupOperationalCredentials & creds = keyset.operational_keys[mKeyIndex++];
1996 25 : if (creds.hash == mSessionId)
1997 : {
1998 9 : TEMPORARY_RETURN_IGNORED mGroupKeyContext.Initialize(creds.encryption_key, mSessionId, creds.privacy_key);
1999 9 : output.fabric_index = fabric.fabric_index;
2000 9 : output.group_id = mapping.group_id;
2001 9 : output.security_policy = keyset.policy;
2002 9 : output.keyContext = &mGroupKeyContext;
2003 9 : return true;
2004 : }
2005 67 : }
2006 :
2007 2 : return false;
2008 : }
2009 :
2010 9 : void GroupDataProviderImpl::GroupSessionIteratorImpl::Release()
2011 : {
2012 9 : mGroupKeyContext.ReleaseKeys();
2013 9 : mProvider.mGroupSessionsIterator.ReleaseObject(this);
2014 9 : }
2015 :
2016 : namespace {
2017 :
2018 : GroupDataProvider * gGroupsProvider = nullptr;
2019 :
2020 : } // namespace
2021 :
2022 93 : GroupDataProvider * GetGroupDataProvider()
2023 : {
2024 93 : return gGroupsProvider;
2025 : }
2026 :
2027 142 : void SetGroupDataProvider(GroupDataProvider * provider)
2028 : {
2029 142 : gGroupsProvider = provider;
2030 142 : }
2031 :
2032 : } // namespace Credentials
2033 : } // namespace chip
|