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 5 : CHIP_ERROR DefaultICDClientStorage::UpdateFabricList(FabricIndex fabricIndex)
43 : {
44 6 : for (auto & fabric_idx : mFabricList)
45 : {
46 2 : if (fabric_idx == fabricIndex)
47 : {
48 1 : return CHIP_NO_ERROR;
49 : }
50 : }
51 :
52 4 : mFabricList.push_back(fabricIndex);
53 :
54 4 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
55 4 : size_t counter = mFabricList.size();
56 4 : size_t total = kFabricIndexTlvSize * counter + kArrayOverHead;
57 4 : ReturnErrorCodeIf(!backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
58 4 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
59 :
60 : TLV::TLVType arrayType;
61 4 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
62 9 : for (auto & fabric_idx : mFabricList)
63 : {
64 5 : ReturnErrorOnFailure(writer.Put(TLV::AnonymousTag(), fabric_idx));
65 : }
66 4 : ReturnErrorOnFailure(writer.EndContainer(arrayType));
67 :
68 4 : const auto len = writer.GetLengthWritten();
69 4 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
70 :
71 4 : writer.Finalize(backingBuffer);
72 8 : return mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName(), backingBuffer.Get(),
73 4 : static_cast<uint16_t>(len));
74 4 : }
75 :
76 4 : CHIP_ERROR DefaultICDClientStorage::LoadFabricList()
77 : {
78 4 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
79 4 : ReturnErrorCodeIf(!backingBuffer.Calloc(kMaxFabricListTlvLength), CHIP_ERROR_NO_MEMORY);
80 4 : uint16_t length = kMaxFabricListTlvLength;
81 4 : ReturnErrorOnFailure(
82 : mpClientInfoStore->SyncGetKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName(), backingBuffer.Get(), length));
83 :
84 1 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
85 1 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
86 : TLV::TLVType arrayType;
87 1 : ReturnErrorOnFailure(reader.EnterContainer(arrayType));
88 :
89 2 : while ((reader.Next(TLV::kTLVType_UnsignedInteger, TLV::AnonymousTag())) == CHIP_NO_ERROR)
90 : {
91 : FabricIndex fabricIndex;
92 1 : ReturnErrorOnFailure(reader.Get(fabricIndex));
93 1 : mFabricList.push_back(fabricIndex);
94 : }
95 :
96 1 : ReturnErrorOnFailure(reader.ExitContainer(arrayType));
97 1 : return reader.VerifyEndOfContainer();
98 4 : }
99 :
100 6 : DefaultICDClientStorage::ICDClientInfoIteratorImpl::ICDClientInfoIteratorImpl(DefaultICDClientStorage & manager) : mManager(manager)
101 : {
102 6 : mFabricListIndex = 0;
103 6 : mClientInfoIndex = 0;
104 6 : mClientInfoVector.clear();
105 6 : }
106 :
107 6 : size_t DefaultICDClientStorage::ICDClientInfoIteratorImpl::Count()
108 : {
109 6 : size_t total = 0;
110 16 : for (auto & fabric_idx : mManager.mFabricList)
111 : {
112 10 : size_t count = 0;
113 10 : size_t clientInfoSize = 0;
114 10 : if (mManager.LoadCounter(fabric_idx, count, clientInfoSize) != CHIP_NO_ERROR)
115 : {
116 0 : return 0;
117 : };
118 : IgnoreUnusedVariable(clientInfoSize);
119 10 : total += count;
120 : }
121 :
122 6 : return total;
123 : }
124 :
125 7 : bool DefaultICDClientStorage::ICDClientInfoIteratorImpl::Next(ICDClientInfo & item)
126 : {
127 11 : for (; mFabricListIndex < mManager.mFabricList.size(); mFabricListIndex++)
128 : {
129 8 : if (mClientInfoVector.size() == 0)
130 : {
131 6 : size_t clientInfoSize = 0;
132 6 : if (mManager.Load(mManager.mFabricList[mFabricListIndex], mClientInfoVector, clientInfoSize) != CHIP_NO_ERROR)
133 : {
134 0 : continue;
135 : }
136 : IgnoreUnusedVariable(clientInfoSize);
137 : }
138 8 : if (mClientInfoIndex < mClientInfoVector.size())
139 : {
140 4 : item = mClientInfoVector[mClientInfoIndex];
141 4 : mClientInfoIndex++;
142 4 : return true;
143 : }
144 4 : mClientInfoIndex = 0;
145 4 : mClientInfoVector.clear();
146 : }
147 :
148 3 : return false;
149 : }
150 :
151 6 : void DefaultICDClientStorage::ICDClientInfoIteratorImpl::Release()
152 : {
153 6 : mManager.mICDClientInfoIterators.ReleaseObject(this);
154 6 : }
155 :
156 4 : CHIP_ERROR DefaultICDClientStorage::Init(PersistentStorageDelegate * clientInfoStore, Crypto::SymmetricKeystore * keyStore)
157 : {
158 4 : VerifyOrReturnError(clientInfoStore != nullptr && keyStore != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
159 4 : VerifyOrReturnError(mpClientInfoStore == nullptr && mpKeyStore == nullptr, CHIP_ERROR_INCORRECT_STATE);
160 4 : mpClientInfoStore = clientInfoStore;
161 4 : mpKeyStore = keyStore;
162 4 : CHIP_ERROR err = LoadFabricList();
163 4 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
164 : {
165 3 : err = CHIP_NO_ERROR;
166 : }
167 4 : return err;
168 : }
169 :
170 6 : DefaultICDClientStorage::ICDClientInfoIterator * DefaultICDClientStorage::IterateICDClientInfo()
171 : {
172 6 : return mICDClientInfoIterators.CreateObject(*this);
173 : }
174 :
175 38 : CHIP_ERROR DefaultICDClientStorage::LoadCounter(FabricIndex fabricIndex, size_t & count, size_t & clientInfoSize)
176 : {
177 38 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
178 38 : size_t len = MaxICDCounterSize();
179 38 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
180 38 : ReturnErrorCodeIf(!backingBuffer.Calloc(len), CHIP_ERROR_NO_MEMORY);
181 38 : uint16_t length = static_cast<uint16_t>(len);
182 :
183 38 : CHIP_ERROR err = mpClientInfoStore->SyncGetKeyValue(
184 76 : DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName(), backingBuffer.Get(), length);
185 38 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
186 : {
187 10 : return CHIP_NO_ERROR;
188 : }
189 28 : ReturnErrorOnFailure(err);
190 :
191 28 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
192 28 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
193 : TLV::TLVType structType;
194 28 : ReturnErrorOnFailure(reader.EnterContainer(structType));
195 28 : uint32_t tempCount = 0;
196 28 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(CounterTag::kCount)));
197 28 : ReturnErrorOnFailure(reader.Get(tempCount));
198 28 : count = static_cast<size_t>(tempCount);
199 :
200 28 : uint32_t tempClientInfoSize = 0;
201 28 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(CounterTag::kSize)));
202 28 : ReturnErrorOnFailure(reader.Get(tempClientInfoSize));
203 28 : clientInfoSize = static_cast<size_t>(tempClientInfoSize);
204 :
205 28 : ReturnErrorOnFailure(reader.ExitContainer(structType));
206 28 : return reader.VerifyEndOfContainer();
207 38 : }
208 :
209 17 : CHIP_ERROR DefaultICDClientStorage::Load(FabricIndex fabricIndex, std::vector<ICDClientInfo> & clientInfoVector,
210 : size_t & clientInfoSize)
211 : {
212 17 : size_t count = 0;
213 17 : ReturnErrorOnFailure(LoadCounter(fabricIndex, count, clientInfoSize));
214 17 : size_t len = clientInfoSize * count + kArrayOverHead;
215 17 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
216 17 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
217 17 : ReturnErrorCodeIf(!backingBuffer.Calloc(len), CHIP_ERROR_NO_MEMORY);
218 17 : uint16_t length = static_cast<uint16_t>(len);
219 17 : CHIP_ERROR err = mpClientInfoStore->SyncGetKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(fabricIndex).KeyName(),
220 17 : backingBuffer.Get(), length);
221 17 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
222 : {
223 5 : return CHIP_NO_ERROR;
224 : }
225 12 : ReturnErrorOnFailure(err);
226 :
227 12 : TLV::ScopedBufferTLVReader reader(std::move(backingBuffer), length);
228 :
229 12 : ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
230 : TLV::TLVType arrayType;
231 12 : ReturnErrorOnFailure(reader.EnterContainer(arrayType));
232 :
233 26 : while ((err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())) == CHIP_NO_ERROR)
234 : {
235 14 : ICDClientInfo clientInfo;
236 : TLV::TLVType ICDClientInfoType;
237 : NodeId nodeId;
238 : FabricIndex fabric;
239 14 : ReturnErrorOnFailure(reader.EnterContainer(ICDClientInfoType));
240 : // Peer Node ID
241 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kPeerNodeId)));
242 14 : ReturnErrorOnFailure(reader.Get(nodeId));
243 :
244 : // Fabric Index
245 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kFabricIndex)));
246 14 : ReturnErrorOnFailure(reader.Get(fabric));
247 14 : clientInfo.peer_node = ScopedNodeId(nodeId, fabric);
248 :
249 : // Start ICD Counter
250 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kStartICDCounter)));
251 14 : ReturnErrorOnFailure(reader.Get(clientInfo.start_icd_counter));
252 :
253 : // Offset
254 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kOffset)));
255 14 : ReturnErrorOnFailure(reader.Get(clientInfo.offset));
256 :
257 : // MonitoredSubject
258 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kMonitoredSubject)));
259 14 : ReturnErrorOnFailure(reader.Get(clientInfo.monitored_subject));
260 :
261 : // Aes key handle
262 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kAesKeyHandle)));
263 14 : ByteSpan aesBuf;
264 14 : ReturnErrorOnFailure(reader.Get(aesBuf));
265 14 : VerifyOrReturnError(aesBuf.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INTERNAL);
266 14 : memcpy(clientInfo.aes_key_handle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), aesBuf.data(),
267 : sizeof(Crypto::Symmetric128BitsKeyByteArray));
268 :
269 : // Hmac key handle
270 14 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle)));
271 14 : ByteSpan hmacBuf;
272 14 : ReturnErrorOnFailure(reader.Get(hmacBuf));
273 14 : VerifyOrReturnError(hmacBuf.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INTERNAL);
274 14 : memcpy(clientInfo.hmac_key_handle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), hmacBuf.data(),
275 : sizeof(Crypto::Symmetric128BitsKeyByteArray));
276 :
277 14 : ReturnErrorOnFailure(reader.ExitContainer(ICDClientInfoType));
278 14 : clientInfoVector.push_back(clientInfo);
279 14 : }
280 :
281 12 : if (err != CHIP_END_OF_TLV)
282 : {
283 0 : return err;
284 : }
285 :
286 12 : ReturnErrorOnFailure(reader.ExitContainer(arrayType));
287 12 : return reader.VerifyEndOfContainer();
288 17 : }
289 :
290 8 : CHIP_ERROR DefaultICDClientStorage::SetKey(ICDClientInfo & clientInfo, const ByteSpan keyData)
291 : {
292 8 : VerifyOrReturnError(keyData.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INVALID_ARGUMENT);
293 :
294 : Crypto::Symmetric128BitsKeyByteArray keyMaterial;
295 8 : memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray));
296 :
297 : // TODO : Update key lifetime once creaKey method supports it.
298 8 : ReturnErrorOnFailure(mpKeyStore->CreateKey(keyMaterial, clientInfo.aes_key_handle));
299 8 : CHIP_ERROR err = mpKeyStore->CreateKey(keyMaterial, clientInfo.hmac_key_handle);
300 8 : if (err != CHIP_NO_ERROR)
301 : {
302 0 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
303 : }
304 8 : return err;
305 : }
306 :
307 5 : void DefaultICDClientStorage::RemoveKey(ICDClientInfo & clientInfo)
308 : {
309 5 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
310 5 : mpKeyStore->DestroyKey(clientInfo.hmac_key_handle);
311 5 : }
312 :
313 10 : CHIP_ERROR DefaultICDClientStorage::SerializeToTlv(TLV::TLVWriter & writer, const std::vector<ICDClientInfo> & clientInfoVector)
314 : {
315 : TLV::TLVType arrayType;
316 10 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
317 21 : for (auto & clientInfo : clientInfoVector)
318 : {
319 : TLV::TLVType ICDClientInfoContainerType;
320 11 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, ICDClientInfoContainerType));
321 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kPeerNodeId), clientInfo.peer_node.GetNodeId()));
322 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kFabricIndex), clientInfo.peer_node.GetFabricIndex()));
323 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kStartICDCounter), clientInfo.start_icd_counter));
324 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kOffset), clientInfo.offset));
325 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kMonitoredSubject), clientInfo.monitored_subject));
326 11 : ByteSpan aesBuf(clientInfo.aes_key_handle.As<Crypto::Symmetric128BitsKeyByteArray>());
327 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kAesKeyHandle), aesBuf));
328 11 : ByteSpan hmacBuf(clientInfo.hmac_key_handle.As<Crypto::Symmetric128BitsKeyByteArray>());
329 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle), hmacBuf));
330 11 : ReturnErrorOnFailure(writer.EndContainer(ICDClientInfoContainerType));
331 : }
332 10 : return writer.EndContainer(arrayType);
333 : }
334 :
335 7 : CHIP_ERROR DefaultICDClientStorage::StoreEntry(const ICDClientInfo & clientInfo)
336 : {
337 7 : std::vector<ICDClientInfo> clientInfoVector;
338 7 : size_t clientInfoSize = MaxICDClientInfoSize();
339 7 : ReturnErrorOnFailure(Load(clientInfo.peer_node.GetFabricIndex(), clientInfoVector, clientInfoSize));
340 :
341 9 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
342 : {
343 3 : if (clientInfo.peer_node.GetNodeId() == it->peer_node.GetNodeId())
344 : {
345 1 : ReturnErrorOnFailure(DecreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex()));
346 1 : clientInfoVector.erase(it);
347 1 : break;
348 : }
349 : }
350 :
351 7 : clientInfoVector.push_back(clientInfo);
352 7 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
353 7 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
354 7 : ReturnErrorCodeIf(!backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
355 7 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
356 :
357 7 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
358 :
359 7 : const auto len = writer.GetLengthWritten();
360 7 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
361 :
362 7 : writer.Finalize(backingBuffer);
363 7 : ReturnErrorOnFailure(mpClientInfoStore->SyncSetKeyValue(
364 : DefaultStorageKeyAllocator::ICDClientInfoKey(clientInfo.peer_node.GetFabricIndex()).KeyName(), backingBuffer.Get(),
365 : static_cast<uint16_t>(len)));
366 :
367 7 : return IncreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex());
368 7 : }
369 :
370 7 : CHIP_ERROR DefaultICDClientStorage::IncreaseEntryCountForFabric(FabricIndex fabricIndex)
371 : {
372 7 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ true);
373 : }
374 :
375 4 : CHIP_ERROR DefaultICDClientStorage::DecreaseEntryCountForFabric(FabricIndex fabricIndex)
376 : {
377 4 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ false);
378 : }
379 :
380 11 : CHIP_ERROR DefaultICDClientStorage::UpdateEntryCountForFabric(FabricIndex fabricIndex, bool increase)
381 : {
382 11 : size_t count = 0;
383 11 : size_t clientInfoSize = MaxICDClientInfoSize();
384 11 : ReturnErrorOnFailure(LoadCounter(fabricIndex, count, clientInfoSize));
385 11 : if (increase)
386 : {
387 7 : count++;
388 : }
389 : else
390 : {
391 4 : count--;
392 : }
393 :
394 11 : size_t total = MaxICDCounterSize();
395 11 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
396 11 : ReturnErrorCodeIf(!backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
397 11 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
398 :
399 : TLV::TLVType structType;
400 11 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, structType));
401 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kCount), static_cast<uint32_t>(count)));
402 11 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kSize), static_cast<uint32_t>(clientInfoSize)));
403 11 : ReturnErrorOnFailure(writer.EndContainer(structType));
404 :
405 11 : const auto len = writer.GetLengthWritten();
406 11 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
407 11 : writer.Finalize(backingBuffer);
408 :
409 22 : return mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName(),
410 22 : backingBuffer.Get(), static_cast<uint16_t>(len));
411 11 : }
412 :
413 3 : CHIP_ERROR DefaultICDClientStorage::DeleteEntry(const ScopedNodeId & peerNode)
414 : {
415 3 : size_t clientInfoSize = 0;
416 3 : std::vector<ICDClientInfo> clientInfoVector;
417 3 : ReturnErrorOnFailure(Load(peerNode.GetFabricIndex(), clientInfoVector, clientInfoSize));
418 :
419 3 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
420 : {
421 3 : if (peerNode.GetNodeId() == it->peer_node.GetNodeId())
422 : {
423 3 : RemoveKey(*it);
424 3 : it = clientInfoVector.erase(it);
425 3 : break;
426 : }
427 : }
428 :
429 3 : ReturnErrorOnFailure(
430 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName()));
431 :
432 3 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
433 3 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
434 3 : ReturnErrorCodeIf(!backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
435 3 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
436 :
437 3 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
438 :
439 3 : const auto len = writer.GetLengthWritten();
440 3 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
441 :
442 3 : writer.Finalize(backingBuffer);
443 3 : ReturnErrorOnFailure(
444 : mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName(),
445 : backingBuffer.Get(), static_cast<uint16_t>(len)));
446 :
447 3 : return DecreaseEntryCountForFabric(peerNode.GetFabricIndex());
448 3 : }
449 :
450 1 : CHIP_ERROR DefaultICDClientStorage::DeleteAllEntries(FabricIndex fabricIndex)
451 : {
452 1 : size_t clientInfoSize = 0;
453 1 : std::vector<ICDClientInfo> clientInfoVector;
454 1 : ReturnErrorOnFailure(Load(fabricIndex, clientInfoVector, clientInfoSize));
455 : IgnoreUnusedVariable(clientInfoSize);
456 3 : for (auto & clientInfo : clientInfoVector)
457 : {
458 2 : RemoveKey(clientInfo);
459 : }
460 1 : ReturnErrorOnFailure(
461 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(fabricIndex).KeyName()));
462 1 : return mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName());
463 1 : }
464 :
465 2 : CHIP_ERROR DefaultICDClientStorage::ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo,
466 : CounterType & counter)
467 : {
468 : uint8_t appDataBuffer[kAppDataLength];
469 2 : MutableByteSpan appData(appDataBuffer);
470 2 : auto * iterator = IterateICDClientInfo();
471 2 : VerifyOrReturnError(iterator != nullptr, CHIP_ERROR_NO_MEMORY);
472 3 : while (iterator->Next(clientInfo))
473 : {
474 2 : CHIP_ERROR err = chip::Protocols::SecureChannel::CheckinMessage::ParseCheckinMessagePayload(
475 2 : clientInfo.aes_key_handle, clientInfo.hmac_key_handle, payload, counter, appData);
476 2 : if (CHIP_NO_ERROR == err)
477 : {
478 1 : iterator->Release();
479 1 : return CHIP_NO_ERROR;
480 : }
481 : }
482 1 : iterator->Release();
483 1 : return CHIP_ERROR_NOT_FOUND;
484 : }
485 : } // namespace app
486 : } // namespace chip
|