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 12 : 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 29 : 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 8 : 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 103 : 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 46 : 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 97 : 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() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INTERNAL);
278 51 : memcpy(clientInfo.aes_key_handle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), aesBuf.data(),
279 : sizeof(Crypto::Symmetric128BitsKeyByteArray));
280 :
281 : // Hmac key handle
282 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle)));
283 51 : ByteSpan hmacBuf;
284 51 : ReturnErrorOnFailure(reader.Get(hmacBuf));
285 51 : VerifyOrReturnError(hmacBuf.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INTERNAL);
286 51 : memcpy(clientInfo.hmac_key_handle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), hmacBuf.data(),
287 : sizeof(Crypto::Symmetric128BitsKeyByteArray));
288 :
289 : // ClientType
290 51 : ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kClientType)));
291 51 : ReturnErrorOnFailure(reader.Get(clientInfo.client_type));
292 :
293 51 : ReturnErrorOnFailure(reader.ExitContainer(ICDClientInfoType));
294 51 : clientInfoVector.push_back(clientInfo);
295 51 : }
296 :
297 46 : if (err != CHIP_END_OF_TLV)
298 : {
299 0 : return err;
300 : }
301 :
302 46 : ReturnErrorOnFailure(reader.ExitContainer(arrayType));
303 46 : return reader.VerifyEndOfContainer();
304 46 : }
305 :
306 17 : CHIP_ERROR DefaultICDClientStorage::SetKey(ICDClientInfo & clientInfo, const ByteSpan keyData)
307 : {
308 17 : VerifyOrReturnError(keyData.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INVALID_ARGUMENT);
309 :
310 : Crypto::Symmetric128BitsKeyByteArray keyMaterial;
311 17 : memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray));
312 :
313 : // TODO : Update key lifetime once creaKey method supports it.
314 17 : ReturnErrorOnFailure(mpKeyStore->CreateKey(keyMaterial, clientInfo.aes_key_handle));
315 17 : CHIP_ERROR err = mpKeyStore->CreateKey(keyMaterial, clientInfo.hmac_key_handle);
316 17 : if (err != CHIP_NO_ERROR)
317 : {
318 0 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
319 : }
320 17 : return err;
321 : }
322 :
323 13 : void DefaultICDClientStorage::RemoveKey(ICDClientInfo & clientInfo)
324 : {
325 13 : mpKeyStore->DestroyKey(clientInfo.aes_key_handle);
326 13 : mpKeyStore->DestroyKey(clientInfo.hmac_key_handle);
327 13 : }
328 :
329 24 : CHIP_ERROR DefaultICDClientStorage::SerializeToTlv(TLV::TLVWriter & writer, const std::vector<ICDClientInfo> & clientInfoVector)
330 : {
331 : TLV::TLVType arrayType;
332 24 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
333 50 : for (auto & clientInfo : clientInfoVector)
334 : {
335 : TLV::TLVType ICDClientInfoContainerType;
336 26 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, ICDClientInfoContainerType));
337 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kPeerNodeId), clientInfo.peer_node.GetNodeId()));
338 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kCheckInNodeId), clientInfo.check_in_node.GetNodeId()));
339 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kFabricIndex), clientInfo.peer_node.GetFabricIndex()));
340 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kStartICDCounter), clientInfo.start_icd_counter));
341 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kOffset), clientInfo.offset));
342 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kMonitoredSubject), clientInfo.monitored_subject));
343 26 : ByteSpan aesBuf(clientInfo.aes_key_handle.As<Crypto::Symmetric128BitsKeyByteArray>());
344 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kAesKeyHandle), aesBuf));
345 26 : ByteSpan hmacBuf(clientInfo.hmac_key_handle.As<Crypto::Symmetric128BitsKeyByteArray>());
346 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle), hmacBuf));
347 26 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kClientType), clientInfo.client_type));
348 26 : ReturnErrorOnFailure(writer.EndContainer(ICDClientInfoContainerType));
349 : }
350 24 : return writer.EndContainer(arrayType);
351 : }
352 :
353 36 : bool DefaultICDClientStorage::FabricExists(FabricIndex fabricIndex)
354 : {
355 45 : for (auto & fabric_idx : mFabricList)
356 : {
357 41 : if (fabric_idx == fabricIndex)
358 : {
359 32 : return true;
360 : }
361 : }
362 4 : return false;
363 : }
364 :
365 24 : CHIP_ERROR DefaultICDClientStorage::StoreEntry(const ICDClientInfo & clientInfo)
366 : {
367 24 : VerifyOrReturnError(FabricExists(clientInfo.peer_node.GetFabricIndex()), CHIP_ERROR_INVALID_FABRIC_INDEX);
368 21 : std::vector<ICDClientInfo> clientInfoVector;
369 21 : size_t clientInfoSize = MaxICDClientInfoSize();
370 21 : ReturnErrorOnFailure(Load(clientInfo.peer_node.GetFabricIndex(), clientInfoVector, clientInfoSize));
371 :
372 24 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
373 : {
374 9 : if (clientInfo.peer_node.GetNodeId() == it->peer_node.GetNodeId())
375 : {
376 6 : ReturnErrorOnFailure(DecreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex()));
377 6 : clientInfoVector.erase(it);
378 6 : break;
379 : }
380 : }
381 21 : clientInfoVector.push_back(clientInfo);
382 21 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
383 21 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
384 21 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
385 21 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
386 :
387 21 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
388 :
389 21 : const auto len = writer.GetLengthWritten();
390 21 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
391 :
392 21 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
393 21 : ReturnErrorOnFailure(mpClientInfoStore->SyncSetKeyValue(
394 : DefaultStorageKeyAllocator::ICDClientInfoKey(clientInfo.peer_node.GetFabricIndex()).KeyName(), backingBuffer.Get(),
395 : static_cast<uint16_t>(len)));
396 :
397 21 : ReturnErrorOnFailure(IncreaseEntryCountForFabric(clientInfo.peer_node.GetFabricIndex()));
398 21 : ChipLogProgress(ICD,
399 : "Store ICD entry successfully with peer nodeId " ChipLogFormatScopedNodeId
400 : " and checkin nodeId " ChipLogFormatScopedNodeId,
401 : ChipLogValueScopedNodeId(clientInfo.peer_node), ChipLogValueScopedNodeId(clientInfo.check_in_node));
402 21 : return CHIP_NO_ERROR;
403 21 : }
404 :
405 21 : CHIP_ERROR DefaultICDClientStorage::IncreaseEntryCountForFabric(FabricIndex fabricIndex)
406 : {
407 21 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ true);
408 : }
409 :
410 9 : CHIP_ERROR DefaultICDClientStorage::DecreaseEntryCountForFabric(FabricIndex fabricIndex)
411 : {
412 9 : return UpdateEntryCountForFabric(fabricIndex, /*increase*/ false);
413 : }
414 :
415 30 : CHIP_ERROR DefaultICDClientStorage::UpdateEntryCountForFabric(FabricIndex fabricIndex, bool increase)
416 : {
417 30 : size_t count = 0;
418 30 : size_t clientInfoSize = MaxICDClientInfoSize();
419 30 : ReturnErrorOnFailure(LoadCounter(fabricIndex, count, clientInfoSize));
420 30 : if (increase)
421 : {
422 21 : count++;
423 : }
424 : else
425 : {
426 9 : count--;
427 : }
428 :
429 30 : size_t total = MaxICDCounterSize();
430 30 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
431 30 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
432 30 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
433 :
434 : TLV::TLVType structType;
435 30 : ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, structType));
436 30 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kCount), static_cast<uint32_t>(count)));
437 30 : ReturnErrorOnFailure(writer.Put(TLV::ContextTag(CounterTag::kSize), static_cast<uint32_t>(clientInfoSize)));
438 30 : ReturnErrorOnFailure(writer.EndContainer(structType));
439 :
440 30 : const auto len = writer.GetLengthWritten();
441 30 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
442 30 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
443 :
444 60 : return mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName(),
445 60 : backingBuffer.Get(), static_cast<uint16_t>(len));
446 30 : }
447 :
448 4 : CHIP_ERROR DefaultICDClientStorage::DeleteEntry(const ScopedNodeId & peerNode)
449 : {
450 4 : VerifyOrReturnError(FabricExists(peerNode.GetFabricIndex()), CHIP_NO_ERROR);
451 4 : size_t clientInfoSize = 0;
452 4 : std::vector<ICDClientInfo> clientInfoVector;
453 4 : ReturnErrorOnFailure(Load(peerNode.GetFabricIndex(), clientInfoVector, clientInfoSize));
454 4 : VerifyOrReturnError(clientInfoVector.size() > 0, CHIP_NO_ERROR);
455 :
456 3 : for (auto it = clientInfoVector.begin(); it != clientInfoVector.end(); it++)
457 : {
458 3 : if (peerNode.GetNodeId() == it->peer_node.GetNodeId())
459 : {
460 3 : RemoveKey(*it);
461 3 : it = clientInfoVector.erase(it);
462 3 : break;
463 : }
464 : }
465 :
466 3 : ReturnErrorOnFailure(
467 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName()));
468 3 : size_t total = clientInfoSize * clientInfoVector.size() + kArrayOverHead;
469 3 : Platform::ScopedMemoryBuffer<uint8_t> backingBuffer;
470 3 : VerifyOrReturnError(backingBuffer.Calloc(total), CHIP_ERROR_NO_MEMORY);
471 3 : TLV::ScopedBufferTLVWriter writer(std::move(backingBuffer), total);
472 :
473 3 : ReturnErrorOnFailure(SerializeToTlv(writer, clientInfoVector));
474 :
475 3 : const auto len = writer.GetLengthWritten();
476 3 : VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
477 :
478 3 : ReturnErrorOnFailure(writer.Finalize(backingBuffer));
479 3 : ReturnErrorOnFailure(
480 : mpClientInfoStore->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(peerNode.GetFabricIndex()).KeyName(),
481 : backingBuffer.Get(), static_cast<uint16_t>(len)));
482 :
483 3 : ReturnErrorOnFailure(DecreaseEntryCountForFabric(peerNode.GetFabricIndex()));
484 3 : ChipLogProgress(ICD, "Remove ICD entry successfully with peer nodeId " ChipLogFormatScopedNodeId,
485 : ChipLogValueScopedNodeId(peerNode));
486 3 : return CHIP_NO_ERROR;
487 4 : }
488 :
489 8 : CHIP_ERROR DefaultICDClientStorage::DeleteAllEntries(FabricIndex fabricIndex)
490 : {
491 8 : VerifyOrReturnError(FabricExists(fabricIndex), CHIP_NO_ERROR);
492 :
493 7 : size_t clientInfoSize = 0;
494 7 : std::vector<ICDClientInfo> clientInfoVector;
495 7 : ReturnErrorOnFailure(Load(fabricIndex, clientInfoVector, clientInfoSize));
496 : IgnoreUnusedVariable(clientInfoSize);
497 16 : for (auto & clientInfo : clientInfoVector)
498 : {
499 9 : RemoveKey(clientInfo);
500 : }
501 7 : ReturnErrorOnFailure(
502 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDClientInfoKey(fabricIndex).KeyName()));
503 7 : ReturnErrorOnFailure(
504 : mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName()));
505 :
506 8 : for (auto fabric = mFabricList.begin(); fabric != mFabricList.end(); fabric++)
507 : {
508 8 : if (*fabric == fabricIndex)
509 : {
510 7 : mFabricList.erase(fabric);
511 7 : break;
512 : }
513 : }
514 :
515 7 : if (mFabricList.size() == 0)
516 : {
517 4 : return mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::ICDFabricList().KeyName());
518 : }
519 :
520 3 : ReturnErrorOnFailure(StoreFabricList());
521 3 : ChipLogProgress(ICD, "Remove all ICD entries successfully for fabric index %u", fabricIndex);
522 3 : return CHIP_NO_ERROR;
523 7 : }
524 :
525 15 : CHIP_ERROR DefaultICDClientStorage::ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo,
526 : Protocols::SecureChannel::CounterType & counter)
527 : {
528 : uint8_t appDataBuffer[kAppDataLength];
529 15 : MutableByteSpan appData(appDataBuffer);
530 15 : auto * iterator = IterateICDClientInfo();
531 15 : VerifyOrReturnError(iterator != nullptr, CHIP_ERROR_NO_MEMORY);
532 20 : while (iterator->Next(clientInfo))
533 : {
534 16 : CHIP_ERROR err = chip::Protocols::SecureChannel::CheckinMessage::ParseCheckinMessagePayload(
535 16 : clientInfo.aes_key_handle, clientInfo.hmac_key_handle, payload, counter, appData);
536 16 : if (CHIP_NO_ERROR == err)
537 : {
538 11 : iterator->Release();
539 11 : return CHIP_NO_ERROR;
540 : }
541 : }
542 4 : iterator->Release();
543 4 : return CHIP_ERROR_NOT_FOUND;
544 : }
545 :
546 0 : void DefaultICDClientStorage::Shutdown()
547 : {
548 0 : mICDClientInfoIterators.ReleaseAll();
549 0 : mpClientInfoStore = nullptr;
550 0 : mpKeyStore = nullptr;
551 0 : mFabricList.clear();
552 0 : }
553 :
554 : } // namespace app
555 : } // namespace chip
|