LCOV - code coverage report
Current view: top level - app/icd/client - DefaultICDClientStorage.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 259 263 98.5 %
Date: 2024-02-15 08:20:41 Functions: 20 20 100.0 %

          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

Generated by: LCOV version 1.14