Matter SDK Coverage Report
Current view: top level - protocols/secure_channel - DefaultSessionResumptionStorage.cpp (source / functions) Coverage Total Hit
Test: SHA:209dc18e4021e7d0dff8120ccc585909391dd862 Lines: 86.2 % 109 94
Test Date: 2026-06-16 07:34:53 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2022 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 <protocols/secure_channel/DefaultSessionResumptionStorage.h>
      19              : 
      20              : #include <lib/support/Base64.h>
      21              : #include <lib/support/SafeInt.h>
      22              : 
      23              : namespace chip {
      24              : 
      25          312 : CHIP_ERROR DefaultSessionResumptionStorage::FindByScopedNodeId(const ScopedNodeId & node, ResumptionIdStorage & resumptionId,
      26              :                                                                Crypto::P256ECDHDerivedSecret & sharedSecret, CATValues & peerCATs)
      27              : {
      28          312 :     ReturnErrorOnFailure(LoadState(node, resumptionId, sharedSecret, peerCATs));
      29          158 :     return CHIP_NO_ERROR;
      30              : }
      31              : 
      32          161 : CHIP_ERROR DefaultSessionResumptionStorage::FindByResumptionId(ConstResumptionIdView resumptionId, ScopedNodeId & node,
      33              :                                                                Crypto::P256ECDHDerivedSecret & sharedSecret, CATValues & peerCATs)
      34              : {
      35          161 :     ReturnErrorOnFailure(FindNodeByResumptionId(resumptionId, node));
      36              :     ResumptionIdStorage tmpResumptionId;
      37           55 :     ReturnErrorOnFailure(FindByScopedNodeId(node, tmpResumptionId, sharedSecret, peerCATs));
      38           55 :     VerifyOrReturnError(std::equal(tmpResumptionId.begin(), tmpResumptionId.end(), resumptionId.begin(), resumptionId.end()),
      39              :                         CHIP_ERROR_KEY_NOT_FOUND);
      40           55 :     return CHIP_NO_ERROR;
      41              : }
      42              : 
      43          161 : CHIP_ERROR DefaultSessionResumptionStorage::FindNodeByResumptionId(ConstResumptionIdView resumptionId, ScopedNodeId & node)
      44              : {
      45          161 :     ReturnErrorOnFailure(LoadLink(resumptionId, node));
      46           55 :     return CHIP_NO_ERROR;
      47              : }
      48              : 
      49          206 : CHIP_ERROR DefaultSessionResumptionStorage::Save(const ScopedNodeId & node, ConstResumptionIdView resumptionId,
      50              :                                                  const Crypto::P256ECDHDerivedSecret & sharedSecret, const CATValues & peerCATs)
      51              : {
      52          206 :     SessionIndex index;
      53          206 :     ReturnErrorOnFailure(LoadIndex(index));
      54              : 
      55         3698 :     for (size_t i = 0; i < index.mSize; ++i)
      56              :     {
      57         3550 :         if (index.mNodes[i] == node)
      58              :         {
      59              :             // Node already exists in the index.  Save in place.
      60           58 :             CHIP_ERROR err = CHIP_NO_ERROR;
      61              :             ResumptionIdStorage oldResumptionId;
      62           58 :             Crypto::P256ECDHDerivedSecret oldSharedSecret;
      63           58 :             CATValues oldPeerCATs;
      64              :             // This follows the approach in Delete.  Removal of the old
      65              :             // resumption-id-keyed link is best effort.  If we cannot load
      66              :             // state to lookup the resumption ID for the key, the entry in
      67              :             // the link table will be leaked.
      68           58 :             err = LoadState(node, oldResumptionId, oldSharedSecret, oldPeerCATs);
      69          116 :             if (err != CHIP_NO_ERROR)
      70              :             {
      71            0 :                 ChipLogError(SecureChannel,
      72              :                              "LoadState failed; unable to fully delete session resumption record for node " ChipLogFormatX64
      73              :                              ": %" CHIP_ERROR_FORMAT,
      74              :                              ChipLogValueX64(node.GetNodeId()), err.Format());
      75              :             }
      76              :             else
      77              :             {
      78           58 :                 err = DeleteLink(oldResumptionId);
      79          116 :                 if (err != CHIP_NO_ERROR)
      80              :                 {
      81            0 :                     ChipLogError(SecureChannel,
      82              :                                  "DeleteLink failed; unable to fully delete session resumption record for node " ChipLogFormatX64
      83              :                                  ": %" CHIP_ERROR_FORMAT,
      84              :                                  ChipLogValueX64(node.GetNodeId()), err.Format());
      85              :                 }
      86              :             }
      87           58 :             ReturnErrorOnFailure(SaveState(node, resumptionId, sharedSecret, peerCATs));
      88           58 :             ReturnErrorOnFailure(SaveLink(resumptionId, node));
      89           58 :             return CHIP_NO_ERROR;
      90           58 :         }
      91              :     }
      92              : 
      93              :     // Constant product inside a CHIPConfig.h macro; cannot widen at the use site.
      94              :     // NOLINTNEXTLINE(bugprone-implicit-widening-of-multiplication-result)
      95          148 :     if (index.mSize == CHIP_CONFIG_CASE_SESSION_RESUME_CACHE_SIZE)
      96              :     {
      97              :         // TODO: implement LRU for resumption
      98            1 :         ReturnErrorOnFailure(Delete(index.mNodes[0]));
      99            1 :         ReturnErrorOnFailure(LoadIndex(index));
     100              :     }
     101              : 
     102          148 :     ReturnErrorOnFailure(SaveState(node, resumptionId, sharedSecret, peerCATs));
     103          148 :     ReturnErrorOnFailure(SaveLink(resumptionId, node));
     104              : 
     105          148 :     index.mNodes[index.mSize++] = node;
     106          148 :     ReturnErrorOnFailure(SaveIndex(index));
     107              : 
     108          148 :     return CHIP_NO_ERROR;
     109              : }
     110              : 
     111           49 : CHIP_ERROR DefaultSessionResumptionStorage::Delete(const ScopedNodeId & node)
     112              : {
     113           49 :     SessionIndex index;
     114           49 :     ReturnErrorOnFailure(LoadIndex(index));
     115              : 
     116              :     ResumptionIdStorage resumptionId;
     117           49 :     Crypto::P256ECDHDerivedSecret sharedSecret;
     118           49 :     CATValues peerCATs;
     119           49 :     CHIP_ERROR err = LoadState(node, resumptionId, sharedSecret, peerCATs);
     120           98 :     if (err == CHIP_NO_ERROR)
     121              :     {
     122           49 :         err = DeleteLink(resumptionId);
     123           98 :         if (err != CHIP_NO_ERROR && err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     124              :         {
     125            0 :             ChipLogError(SecureChannel,
     126              :                          "Unable to delete session resumption link for node " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     127              :                          ChipLogValueX64(node.GetNodeId()), err.Format());
     128              :         }
     129              :     }
     130            0 :     else if (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     131              :     {
     132            0 :         ChipLogError(SecureChannel,
     133              :                      "Unable to load session resumption state during session deletion for node " ChipLogFormatX64
     134              :                      ": %" CHIP_ERROR_FORMAT,
     135              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     136              :     }
     137              : 
     138           49 :     err = DeleteState(node);
     139           98 :     if (err != CHIP_NO_ERROR && err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     140              :     {
     141            0 :         ChipLogError(SecureChannel, "Unable to delete session resumption state for node " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     142              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     143              :     }
     144              : 
     145           49 :     bool found = false;
     146         1225 :     for (size_t i = 0; i < index.mSize; ++i)
     147              :     {
     148         1176 :         if (found)
     149              :         {
     150              :             // index.mSize was decreased by 1 when found was set to true.
     151              :             // So the (i+1)th element isn't out of bounds.
     152         1127 :             index.mNodes[i] = index.mNodes[i + 1];
     153              :         }
     154              :         else
     155              :         {
     156           49 :             if (index.mNodes[i] == node)
     157              :             {
     158           49 :                 found = true;
     159           49 :                 if (i + 1 < index.mSize)
     160              :                 {
     161           48 :                     index.mNodes[i] = index.mNodes[i + 1];
     162              :                 }
     163           49 :                 index.mSize -= 1;
     164              :             }
     165              :         }
     166              :     }
     167              : 
     168           49 :     if (found)
     169              :     {
     170           49 :         err = SaveIndex(index);
     171           98 :         if (err != CHIP_NO_ERROR)
     172              :         {
     173            0 :             ChipLogError(SecureChannel, "Unable to save session resumption index: %" CHIP_ERROR_FORMAT, err.Format());
     174              :         }
     175              :     }
     176              :     else
     177              :     {
     178            0 :         ChipLogError(SecureChannel,
     179              :                      "Unable to find session resumption state for node in index" ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     180              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     181              :     }
     182              : 
     183           49 :     return CHIP_NO_ERROR;
     184           49 : }
     185              : 
     186           19 : CHIP_ERROR DefaultSessionResumptionStorage::DeleteAll(FabricIndex fabricIndex)
     187              : {
     188           19 :     CHIP_ERROR stickyErr = CHIP_NO_ERROR;
     189           19 :     size_t found         = 0;
     190           19 :     SessionIndex index;
     191           19 :     ReturnErrorOnFailure(LoadIndex(index));
     192           19 :     size_t initialSize = index.mSize;
     193          433 :     for (size_t i = 0; i < initialSize; ++i)
     194              :     {
     195          414 :         CHIP_ERROR err = CHIP_NO_ERROR;
     196          414 :         size_t cur     = i - found;
     197          414 :         size_t remain  = initialSize - i;
     198              :         ResumptionIdStorage resumptionId;
     199          414 :         Crypto::P256ECDHDerivedSecret sharedSecret;
     200          414 :         CATValues peerCATs;
     201          414 :         if (index.mNodes[cur].GetFabricIndex() != fabricIndex)
     202              :         {
     203          363 :             continue;
     204              :         }
     205           51 :         err       = LoadState(index.mNodes[cur], resumptionId, sharedSecret, peerCATs);
     206          102 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     207          102 :         if (err != CHIP_NO_ERROR)
     208              :         {
     209            0 :             ChipLogError(SecureChannel,
     210              :                          "Session resumption cache deletion partially failed for fabric index %u, "
     211              :                          "unable to load node state: %" CHIP_ERROR_FORMAT,
     212              :                          fabricIndex, err.Format());
     213            0 :             continue;
     214              :         }
     215           51 :         err       = DeleteLink(resumptionId);
     216          102 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     217          102 :         if (err != CHIP_NO_ERROR)
     218              :         {
     219            0 :             ChipLogError(SecureChannel,
     220              :                          "Session resumption cache deletion partially failed for fabric index %u, "
     221              :                          "unable to delete node link: %" CHIP_ERROR_FORMAT,
     222              :                          fabricIndex, err.Format());
     223            0 :             continue;
     224              :         }
     225           51 :         err       = DeleteState(index.mNodes[cur]);
     226          102 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     227          102 :         if (err != CHIP_NO_ERROR)
     228              :         {
     229            0 :             ChipLogError(SecureChannel,
     230              :                          "Session resumption cache is in an inconsistent state!  "
     231              :                          "Unable to delete node state during attempted deletion of fabric index %u: %" CHIP_ERROR_FORMAT,
     232              :                          fabricIndex, err.Format());
     233            0 :             continue;
     234              :         }
     235           51 :         ++found;
     236           51 :         --remain;
     237           51 :         if (remain)
     238              :         {
     239           49 :             memmove(&index.mNodes[cur], &index.mNodes[cur + 1], remain * sizeof(index.mNodes[0]));
     240              :         }
     241          414 :     }
     242           19 :     if (found)
     243              :     {
     244           19 :         index.mSize -= found;
     245           19 :         CHIP_ERROR err = SaveIndex(index);
     246           38 :         stickyErr      = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     247           38 :         if (err != CHIP_NO_ERROR)
     248              :         {
     249            0 :             ChipLogError(
     250              :                 SecureChannel,
     251              :                 "Session resumption cache is in an inconsistent state!  "
     252              :                 "Unable to save session resumption index during attempted deletion of fabric index %u: %" CHIP_ERROR_FORMAT,
     253              :                 fabricIndex, err.Format());
     254              :         }
     255              :     }
     256           19 :     return stickyErr;
     257              : }
     258              : 
     259              : } // namespace chip
        

Generated by: LCOV version 2.0-1