Line data Source code
1 : /*
2 : * Copyright (c) 2023 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include <app/icd/client/DefaultICDClientStorage.h>
19 : #include <iterator>
20 : #include <lib/core/Global.h>
21 : #include <lib/support/Base64.h>
22 : #include <lib/support/CodeUtils.h>
23 : #include <lib/support/DefaultStorageKeyAllocator.h>
24 : #include <lib/support/SafeInt.h>
25 : #include <lib/support/logging/CHIPLogging.h>
26 : #include <limits>
27 :
28 : namespace {
29 : // FabricIndex is uint8_t, the tlv size with anonymous tag is 1(control bytes) + 1(value) = 2
30 : constexpr size_t kFabricIndexTlvSize = 2;
31 :
32 : // The array itself has a control byte and an end-of-array marker.
33 : constexpr size_t kArrayOverHead = 2;
34 : constexpr size_t kFabricIndexMax = 255;
35 :
36 : constexpr size_t kMaxFabricListTlvLength = kFabricIndexTlvSize * kFabricIndexMax + kArrayOverHead;
37 : static_assert(kMaxFabricListTlvLength <= std::numeric_limits<uint16_t>::max(), "Expected size for fabric list TLV is too large!");
38 : } // namespace
39 :
40 : namespace chip {
41 : namespace app {
42 13 : CHIP_ERROR DefaultICDClientStorage::UpdateFabricList(FabricIndex fabricIndex)
43 : {
44 17 : for (auto & fabric_idx : mFabricList)
45 : {
46 4 : if (fabric_idx == fabricIndex)
47 : {
48 0 : return CHIP_NO_ERROR;
49 : }
50 : }
51 :
52 13 : mFabricList.push_back(fabricIndex);
53 :
54 13 : return StoreFabricList();
55 : }
56 :
57 16 : CHIP_ERROR DefaultICDClientStorage::StoreFabricList()
58 : {
59 16 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
60 16 : size_t counter = mFabricList.size();
61 16 : size_t total = kFabricIndexTlvSize * counter + kArrayOverHead;
62 16 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
63 16 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
64 :
65 : TLV::TLVType arrayType;
66 16 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
67 36 : for (auto & fabric_idx : mFabricList)
68 : {
69 20 : ReturnErrorOnFailure(writer.Put(TLV::AnonymousTag(), fabric_idx));
70 : }
71 16 : ReturnErrorOnFailure(writer.EndContainer(arrayType));
72 :
73 16 : const auto len = writer.GetLengthWritten();
74 16 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
75 :
76 16 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
77 32 : return mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName(), backingBuffer.Get(),
78 16 : static_cast<uint16_t>(len));
79 16 : }
80 :
81 8 : CHIP_ERROR DefaultICDClientStorage::LoadFabricList()
82 : {
83 8 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
84 8 : VerifyOrReturnError(backingBuffer.Calloc(kMaxFabricListTlvLength), CHIP_ERROR_NO_MEMORY);
85 8 : uint16_t length = kMaxFabricListTlvLength;
86 8 : ReturnErrorOnFailure(
87 : mpClientInfoStore->SyncGetKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName(), backingBuffer.Get(), length));
88 :
89 0 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
90 0 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
91 : TLV::TLVType arrayType;
92 0 : ReturnErrorOnFailure(reader.EnterContainer(arrayType));
93 :
94 0 : while ((reader.Next(TLV::kTLVType_UnsignedInteger, TLV::AnonymousTag())) == CHIP_NO_ERROR)
95 : {
96 : FabricIndex fabricIndex;
97 0 : ReturnErrorOnFailure(reader.Get(fabricIndex));
98 0 : mFabricList.push_back(fabricIndex);
99 : }
100 :
101 0 : ReturnErrorOnFailure(reader.ExitContainer(arrayType));
102 0 : return reader.VerifyEndOfContainer();
103 8 : }
104 :
105 29 : DefaultICDClientStorage::ICDClientInfoIteratorImpl::ICDClientInfoIteratorImpl(DefaultICDClientStorage & manager) : mManager(manager)
106 : {
107 29 : mFabricListIndex = 0;
108 29 : mClientInfoIndex = 0;
109 29 : mClientInfoVector.clear();
110 29 : }
111 :
112 9 : size_t DefaultICDClientStorage::ICDClientInfoIteratorImpl::Count()
113 : {
114 9 : size_t total = 0;
115 21 : for (auto & fabric_idx : mManager.mFabricList)
116 : {
117 12 : size_t count = 0;
118 12 : size_t clientInfoSize = 0;
119 24 : if (mManager.LoadCounter(fabric_idx, count, clientInfoSize) != CHIP_NO_ERROR)
120 : {
121 0 : return 0;
122 : };
123 : IgnoreUnusedVariable(clientInfoSize);
124 12 : total += count;
125 : }
126 :
127 9 : return total;
128 : }
129 :
130 35 : bool DefaultICDClientStorage::ICDClientInfoIteratorImpl::Next(ICDClientInfo & item)
131 : {
132 45 : for (; mFabricListIndex < mManager.mFabricList.size(); mFabricListIndex++)
133 : {
134 38 : if (mClientInfoVector.size() == 0)
135 : {
136 29 : size_t clientInfoSize = 0;
137 58 : if (mManager.Load(mManager.mFabricList[mFabricListIndex], mClientInfoVector, clientInfoSize) != CHIP_NO_ERROR)
138 : {
139 0 : continue;
140 : }
141 : IgnoreUnusedVariable(clientInfoSize);
142 : }
143 38 : if (mClientInfoIndex < mClientInfoVector.size())
144 : {
145 28 : item = mClientInfoVector[mClientInfoIndex];
146 28 : mClientInfoIndex++;
147 28 : return true;
148 : }
149 10 : mClientInfoIndex = 0;
150 10 : mClientInfoVector.clear();
151 : }
152 :
153 7 : return false;
154 : }
155 :
156 29 : void DefaultICDClientStorage::ICDClientInfoIteratorImpl::Release()
157 : {
158 29 : mManager.mICDClientInfoIterators.ReleaseObject(this);
159 29 : }
160 :
161 8 : CHIP_ERROR DefaultICDClientStorage::Init(PersistentStorageDelegate * clientInfoStore, Crypto::SymmetricKeystore * keyStore)
162 : {
163 8 : VerifyOrReturnError(clientInfoStore != nullptr && keyStore != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
164 8 : VerifyOrReturnError(mpClientInfoStore == nullptr && mpKeyStore == nullptr, CHIP_ERROR_INCORRECT_STATE);
165 8 : mpClientInfoStore = clientInfoStore;
166 8 : mpKeyStore = keyStore;
167 8 : CHIP_ERROR err = LoadFabricList();
168 16 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
169 : {
170 8 : err = CHIP_NO_ERROR;
171 : }
172 8 : return err;
173 : }
174 :
175 29 : DefaultICDClientStorage::ICDClientInfoIterator * DefaultICDClientStorage::IterateICDClientInfo()
176 : {
177 29 : return mICDClientInfoIterators.CreateObject(*this);
178 : }
179 :
180 103 : CHIP_ERROR DefaultICDClientStorage::LoadCounter(FabricIndex fabricIndex, size_t & count, size_t & clientInfoSize)
181 : {
182 103 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
183 103 : size_t len = MaxICDCounterSize();
184 103 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
185 103 : VerifyOrReturnError(backingBuffer.Calloc(len), CHIP_ERROR_NO_MEMORY);
186 103 : uint16_t length = static_cast<uint16_t>(len);
187 :
188 103 : CHIP_ERROR err = mpClientInfoStore->SyncGetKeyValue(
189 206 : DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName(), backingBuffer.Get(), length);
190 206 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
191 : {
192 24 : return CHIP_NO_ERROR;
193 : }
194 79 : ReturnErrorOnFailure(err);
195 :
196 79 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
197 79 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
198 : TLV::TLVType structType;
199 79 : ReturnErrorOnFailure(reader.EnterContainer(structType));
200 79 : uint32_t tempCount = 0;
201 79 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(CounterTag::kCount)));
202 79 : ReturnErrorOnFailure(reader.Get(tempCount));
203 79 : count = static_cast<size_t>(tempCount);
204 :
205 79 : uint32_t tempClientInfoSize = 0;
206 79 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(CounterTag::kSize)));
207 79 : ReturnErrorOnFailure(reader.Get(tempClientInfoSize));
208 79 : clientInfoSize = static_cast<size_t>(tempClientInfoSize);
209 :
210 79 : ReturnErrorOnFailure(reader.ExitContainer(structType));
211 79 : return reader.VerifyEndOfContainer();
212 103 : }
213 :
214 61 : CHIP_ERROR DefaultICDClientStorage::Load(FabricIndex fabricIndex, std::vector<ICDClientInfo> & clientInfoVector,
215 : size_t & clientInfoSize)
216 : {
217 61 : size_t count = 0;
218 61 : ReturnErrorOnFailure(LoadCounter(fabricIndex, count, clientInfoSize));
219 61 : VerifyOrReturnError(count > 0, CHIP_NO_ERROR);
220 46 : size_t len = clientInfoSize * count + kArrayOverHead;
221 46 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
222 46 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
223 46 : VerifyOrReturnError(backingBuffer.Calloc(len), CHIP_ERROR_NO_MEMORY);
224 46 : uint16_t length = static_cast<uint16_t>(len);
225 46 : CHIP_ERROR err = mpClientInfoStore->SyncGetKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(fabricIndex).KeyName(),
226 46 : backingBuffer.Get(), length);
227 92 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
228 : {
229 0 : return CHIP_NO_ERROR;
230 : }
231 46 : ReturnErrorOnFailure(err);
232 :
233 46 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
234 :
235 46 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
236 : TLV::TLVType arrayType;
237 46 : ReturnErrorOnFailure(reader.EnterContainer(arrayType));
238 :
239 194 : while ((err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())) == CHIP_NO_ERROR)
240 : {
241 51 : ICDClientInfo clientInfo;
242 : TLV::TLVType ICDClientInfoType;
243 : NodeId nodeId;
244 : NodeId checkInNodeId;
245 : FabricIndex fabric;
246 51 : ReturnErrorOnFailure(reader.EnterContainer(ICDClientInfoType));
247 : // Peer Node ID
248 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kPeerNodeId)));
249 51 : ReturnErrorOnFailure(reader.Get(nodeId));
250 :
251 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kCheckInNodeId)));
252 51 : ReturnErrorOnFailure(reader.Get(checkInNodeId));
253 :
254 : // Fabric Index
255 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kFabricIndex)));
256 51 : ReturnErrorOnFailure(reader.Get(fabric));
257 :
258 51 : clientInfo.peer_node = ScopedNodeId(nodeId, fabric);
259 51 : clientInfo.check_in_node = ScopedNodeId(checkInNodeId, fabric);
260 :
261 : // Start ICD Counter
262 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kStartICDCounter)));
263 51 : ReturnErrorOnFailure(reader.Get(clientInfo.start_icd_counter));
264 :
265 : // Offset
266 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kOffset)));
267 51 : ReturnErrorOnFailure(reader.Get(clientInfo.offset));
268 :
269 : // MonitoredSubject
270 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kMonitoredSubject)));
271 51 : ReturnErrorOnFailure(reader.Get(clientInfo.monitored_subject));
272 :
273 : // Aes key handle
274 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kAesKeyHandle)));
275 51 : ByteSpan aesBuf;
276 51 : ReturnErrorOnFailure(reader.Get(aesBuf));
277 51 : VerifyOrReturnError(aesBuf.size() == Crypto::Aes128KeyHandle::Size(), CHIP_ERROR_INTERNAL);
278 51 : memcpy(clientInfo.aes_key_handle.OpaqueBytes().data(), aesBuf.data(), Crypto::Aes128KeyHandle::Size());
279 :
280 : // Hmac key handle
281 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle)));
282 51 : ByteSpan hmacBuf;
283 51 : ReturnErrorOnFailure(reader.Get(hmacBuf));
284 51 : VerifyOrReturnError(hmacBuf.size() == Crypto::Hmac128KeyHandle::Size(), CHIP_ERROR_INTERNAL);
285 51 : memcpy(clientInfo.hmac_key_handle.OpaqueBytes().data(), hmacBuf.data(), Crypto::Hmac128KeyHandle::Size());
286 :
287 : // ClientType
288 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kClientType)));
289 51 : ReturnErrorOnFailure(reader.Get(clientInfo.client_type));
290 :
291 51 : ReturnErrorOnFailure(reader.ExitContainer(ICDClientInfoType));
292 51 : clientInfoVector.push_back(clientInfo);
293 51 : }
294 :
295 92 : if (err != CHIP_END_OF_TLV)
296 : {
297 0 : return err;
298 : }
299 :
300 46 : ReturnErrorOnFailure(reader.ExitContainer(arrayType));
301 46 : return reader.VerifyEndOfContainer();
302 46 : }
303 :
304 17 : CHIP_ERROR DefaultICDClientStorage::SetKey(ICDClientInfo & clientInfo, const ByteSpan keyData)
305 : {
306 17 : VerifyOrReturnError(keyData.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INVALID_ARGUMENT);
307 :
308 : Crypto::Symmetric128BitsKeyByteArray keyMaterial;
309 17 : memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray));
310 :
311 : // TODO : Update key lifetime once creaKey method supports it.
312 17 : ReturnErrorOnFailure(mpKeyStore->CreateKey(keyMaterial, clientInfo.aes_key_handle));
313 17 : CHIP_ERROR err = mpKeyStore->CreateKey(keyMaterial, clientInfo.hmac_key_handle);
314 34 : if (err != CHIP_NO_ERROR)
315 : {
316 0 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
317 : }
318 17 : return err;
319 : }
320 :
321 13 : void DefaultICDClientStorage::RemoveKey(ICDClientInfo & clientInfo)
322 : {
323 13 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
324 13 : mpKeyStore->DestroyKey(clientInfo.hmac_key_handle);
325 13 : }
326 :
327 24 : CHIP_ERROR DefaultICDClientStorage::SerializeToTlv(TLV::TLVWriter & writer, const std::vector<ICDClientInfo> & clientInfoVector)
328 : {
329 : TLV::TLVType arrayType;
330 24 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
331 50 : for (auto & clientInfo : clientInfoVector)
332 : {
333 : TLV::TLVType ICDClientInfoContainerType;
334 26 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, ICDClientInfoContainerType));
335 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kPeerNodeId), clientInfo.peer_node.GetNodeId()));
336 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kCheckInNodeId), clientInfo.check_in_node.GetNodeId()));
337 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kFabricIndex), clientInfo.peer_node.GetFabricIndex()));
338 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kStartICDCounter), clientInfo.start_icd_counter));
339 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kOffset), clientInfo.offset));
340 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kMonitoredSubject), clientInfo.monitored_subject));
341 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kAesKeyHandle), clientInfo.aes_key_handle.OpaqueBytes()));
342 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle), clientInfo.hmac_key_handle.OpaqueBytes()));
343 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kClientType), clientInfo.client_type));
344 26 : ReturnErrorOnFailure(writer.EndContainer(ICDClientInfoContainerType));
345 : }
346 24 : return writer.EndContainer(arrayType);
347 : }
348 :
349 36 : bool DefaultICDClientStorage::FabricExists(FabricIndex fabricIndex)
350 : {
351 45 : for (auto & fabric_idx : mFabricList)
352 : {
353 41 : if (fabric_idx == fabricIndex)
354 : {
355 32 : return true;
356 : }
357 : }
358 4 : return false;
359 : }
360 :
361 24 : CHIP_ERROR DefaultICDClientStorage::StoreEntry(const ICDClientInfo & clientInfo)
362 : {
363 24 : VerifyOrReturnError(FabricExists(clientInfo.peer_node.GetFabricIndex()), CHIP_ERROR_INVALID_FABRIC_INDEX);
364 21 : std::vector<ICDClientInfo> clientInfoVector;
365 21 : size_t clientInfoSize = MaxICDClientInfoSize();
366 21 : ReturnErrorOnFailure(Load(clientInfo.peer_node.GetFabricIndex(), clientInfoVector, clientInfoSize));
367 :
368 24 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
369 : {
370 9 : if (clientInfo.peer_node.GetNodeId() == it->peer_node.GetNodeId())
371 : {
372 6 : ReturnErrorOnFailure(DecreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex()));
373 6 : clientInfoVector.erase(it);
374 6 : break;
375 : }
376 : }
377 21 : clientInfoVector.push_back(clientInfo);
378 21 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
379 21 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
380 21 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
381 21 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
382 :
383 21 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
384 :
385 21 : const auto len = writer.GetLengthWritten();
386 21 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
387 :
388 21 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
389 21 : ReturnErrorOnFailure(mpClientInfoStore->SyncSetKeyValue(
390 : DefaultStorageKeyAllocator::ICDClientInfoKey(clientInfo.peer_node.GetFabricIndex()).KeyName(), backingBuffer.Get(),
391 : static_cast<uint16_t>(len)));
392 :
393 21 : ReturnErrorOnFailure(IncreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex()));
394 21 : ChipLogProgress(ICD,
395 : "Store ICD entry successfully with peer nodeId " ChipLogFormatScopedNodeId
396 : " and checkin nodeId " ChipLogFormatScopedNodeId,
397 : ChipLogValueScopedNodeId(clientInfo.peer_node), ChipLogValueScopedNodeId(clientInfo.check_in_node));
398 21 : return CHIP_NO_ERROR;
399 21 : }
400 :
401 21 : CHIP_ERROR DefaultICDClientStorage::IncreaseEntryCountForFabric(FabricIndex fabricIndex)
402 : {
403 21 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ true);
404 : }
405 :
406 9 : CHIP_ERROR DefaultICDClientStorage::DecreaseEntryCountForFabric(FabricIndex fabricIndex)
407 : {
408 9 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ false);
409 : }
410 :
411 30 : CHIP_ERROR DefaultICDClientStorage::UpdateEntryCountForFabric(FabricIndex fabricIndex, bool increase)
412 : {
413 30 : size_t count = 0;
414 30 : size_t clientInfoSize = MaxICDClientInfoSize();
415 30 : ReturnErrorOnFailure(LoadCounter(fabricIndex, count, clientInfoSize));
416 30 : if (increase)
417 : {
418 21 : count++;
419 : }
420 : else
421 : {
422 9 : count--;
423 : }
424 :
425 30 : size_t total = MaxICDCounterSize();
426 30 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
427 30 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
428 30 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
429 :
430 : TLV::TLVType structType;
431 30 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, structType));
432 30 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kCount), static_cast<uint32_t>(count)));
433 30 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kSize), static_cast<uint32_t>(clientInfoSize)));
434 30 : ReturnErrorOnFailure(writer.EndContainer(structType));
435 :
436 30 : const auto len = writer.GetLengthWritten();
437 30 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
438 30 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
439 :
440 60 : return mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName(),
441 60 : backingBuffer.Get(), static_cast<uint16_t>(len));
442 30 : }
443 :
444 4 : CHIP_ERROR DefaultICDClientStorage::DeleteEntry(const ScopedNodeId & peerNode)
445 : {
446 4 : VerifyOrReturnError(FabricExists(peerNode.GetFabricIndex()), CHIP_NO_ERROR);
447 4 : size_t clientInfoSize = 0;
448 4 : std::vector<ICDClientInfo> clientInfoVector;
449 4 : ReturnErrorOnFailure(Load(peerNode.GetFabricIndex(), clientInfoVector, clientInfoSize));
450 4 : VerifyOrReturnError(clientInfoVector.size() > 0, CHIP_NO_ERROR);
451 :
452 3 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
453 : {
454 3 : if (peerNode.GetNodeId() == it->peer_node.GetNodeId())
455 : {
456 3 : RemoveKey(*it);
457 3 : it = clientInfoVector.erase(it);
458 3 : break;
459 : }
460 : }
461 :
462 3 : ReturnErrorOnFailure(
463 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName()));
464 3 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
465 3 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
466 3 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
467 3 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
468 :
469 3 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
470 :
471 3 : const auto len = writer.GetLengthWritten();
472 3 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
473 :
474 3 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
475 3 : ReturnErrorOnFailure(
476 : mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName(),
477 : backingBuffer.Get(), static_cast<uint16_t>(len)));
478 :
479 3 : ReturnErrorOnFailure(DecreaseEntryCountForFabric(peerNode.GetFabricIndex()));
480 3 : ChipLogProgress(ICD, "Remove ICD entry successfully with peer nodeId " ChipLogFormatScopedNodeId,
481 : ChipLogValueScopedNodeId(peerNode));
482 3 : return CHIP_NO_ERROR;
483 4 : }
484 :
485 8 : CHIP_ERROR DefaultICDClientStorage::DeleteAllEntries(FabricIndex fabricIndex)
486 : {
487 8 : VerifyOrReturnError(FabricExists(fabricIndex), CHIP_NO_ERROR);
488 :
489 7 : size_t clientInfoSize = 0;
490 7 : std::vector<ICDClientInfo> clientInfoVector;
491 7 : ReturnErrorOnFailure(Load(fabricIndex, clientInfoVector, clientInfoSize));
492 : IgnoreUnusedVariable(clientInfoSize);
493 16 : for (auto & clientInfo : clientInfoVector)
494 : {
495 9 : RemoveKey(clientInfo);
496 : }
497 7 : ReturnErrorOnFailure(
498 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(fabricIndex).KeyName()));
499 7 : ReturnErrorOnFailure(
500 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName()));
501 :
502 8 : for (auto fabric = mFabricList.begin(); fabric != mFabricList.end(); fabric++)
503 : {
504 8 : if (*fabric == fabricIndex)
505 : {
506 7 : mFabricList.erase(fabric);
507 7 : break;
508 : }
509 : }
510 :
511 7 : if (mFabricList.size() == 0)
512 : {
513 4 : return mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName());
514 : }
515 :
516 3 : ReturnErrorOnFailure(StoreFabricList());
517 3 : ChipLogProgress(ICD, "Remove all ICD entries successfully for fabric index %u", fabricIndex);
518 3 : return CHIP_NO_ERROR;
519 7 : }
520 :
521 15 : CHIP_ERROR DefaultICDClientStorage::ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo,
522 : Protocols::SecureChannel::CounterType & counter)
523 : {
524 : uint8_t appDataBuffer[kAppDataLength];
525 15 : MutableByteSpan appData(appDataBuffer);
526 15 : auto * iterator = IterateICDClientInfo();
527 15 : VerifyOrReturnError(iterator != nullptr, CHIP_ERROR_NO_MEMORY);
528 20 : while (iterator->Next(clientInfo))
529 : {
530 16 : CHIP_ERROR err = chip::Protocols::SecureChannel::CheckinMessage::ParseCheckinMessagePayload(
531 16 : clientInfo.aes_key_handle, clientInfo.hmac_key_handle, payload, counter, appData);
532 32 : if (CHIP_NO_ERROR == err)
533 : {
534 11 : iterator->Release();
535 11 : return CHIP_NO_ERROR;
536 : }
537 : }
538 4 : iterator->Release();
539 4 : return CHIP_ERROR_NOT_FOUND;
540 : }
541 :
542 0 : void DefaultICDClientStorage::Shutdown()
543 : {
544 0 : mICDClientInfoIterators.ReleaseAll();
545 0 : mpClientInfoStore = nullptr;
546 0 : mpKeyStore = nullptr;
547 0 : mFabricList.clear();
548 0 : }
549 :
550 : } // namespace app
551 : } // namespace chip
|