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