Matter SDK Coverage Report
Current view: top level - protocols/secure_channel - DefaultSessionResumptionStorage.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 86.2 % 109 94
Test Date: 2025-01-17 19:00:11 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           58 :             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           58 :                 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          148 :     if (index.mSize == CHIP_CONFIG_CASE_SESSION_RESUME_CACHE_SIZE)
      94              :     {
      95              :         // TODO: implement LRU for resumption
      96            1 :         ReturnErrorOnFailure(Delete(index.mNodes[0]));
      97            1 :         ReturnErrorOnFailure(LoadIndex(index));
      98              :     }
      99              : 
     100          148 :     ReturnErrorOnFailure(SaveState(node, resumptionId, sharedSecret, peerCATs));
     101          148 :     ReturnErrorOnFailure(SaveLink(resumptionId, node));
     102              : 
     103          148 :     index.mNodes[index.mSize++] = node;
     104          148 :     ReturnErrorOnFailure(SaveIndex(index));
     105              : 
     106          148 :     return CHIP_NO_ERROR;
     107              : }
     108              : 
     109           49 : CHIP_ERROR DefaultSessionResumptionStorage::Delete(const ScopedNodeId & node)
     110              : {
     111           49 :     SessionIndex index;
     112           49 :     ReturnErrorOnFailure(LoadIndex(index));
     113              : 
     114              :     ResumptionIdStorage resumptionId;
     115           49 :     Crypto::P256ECDHDerivedSecret sharedSecret;
     116           49 :     CATValues peerCATs;
     117           49 :     CHIP_ERROR err = LoadState(node, resumptionId, sharedSecret, peerCATs);
     118           49 :     if (err == CHIP_NO_ERROR)
     119              :     {
     120           49 :         err = DeleteLink(resumptionId);
     121           49 :         if (err != CHIP_NO_ERROR && err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     122              :         {
     123            0 :             ChipLogError(SecureChannel,
     124              :                          "Unable to delete session resumption link for node " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     125              :                          ChipLogValueX64(node.GetNodeId()), err.Format());
     126              :         }
     127              :     }
     128            0 :     else if (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     129              :     {
     130            0 :         ChipLogError(SecureChannel,
     131              :                      "Unable to load session resumption state during session deletion for node " ChipLogFormatX64
     132              :                      ": %" CHIP_ERROR_FORMAT,
     133              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     134              :     }
     135              : 
     136           49 :     err = DeleteState(node);
     137           49 :     if (err != CHIP_NO_ERROR && err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     138              :     {
     139            0 :         ChipLogError(SecureChannel, "Unable to delete session resumption state for node " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     140              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     141              :     }
     142              : 
     143           49 :     bool found = false;
     144         1225 :     for (size_t i = 0; i < index.mSize; ++i)
     145              :     {
     146         1176 :         if (found)
     147              :         {
     148              :             // index.mSize was decreased by 1 when found was set to true.
     149              :             // So the (i+1)th element isn't out of bounds.
     150         1127 :             index.mNodes[i] = index.mNodes[i + 1];
     151              :         }
     152              :         else
     153              :         {
     154           49 :             if (index.mNodes[i] == node)
     155              :             {
     156           49 :                 found = true;
     157           49 :                 if (i + 1 < index.mSize)
     158              :                 {
     159           48 :                     index.mNodes[i] = index.mNodes[i + 1];
     160              :                 }
     161           49 :                 index.mSize -= 1;
     162              :             }
     163              :         }
     164              :     }
     165              : 
     166           49 :     if (found)
     167              :     {
     168           49 :         err = SaveIndex(index);
     169           49 :         if (err != CHIP_NO_ERROR)
     170              :         {
     171            0 :             ChipLogError(SecureChannel, "Unable to save session resumption index: %" CHIP_ERROR_FORMAT, err.Format());
     172              :         }
     173              :     }
     174              :     else
     175              :     {
     176            0 :         ChipLogError(SecureChannel,
     177              :                      "Unable to find session resumption state for node in index" ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
     178              :                      ChipLogValueX64(node.GetNodeId()), err.Format());
     179              :     }
     180              : 
     181           49 :     return CHIP_NO_ERROR;
     182           49 : }
     183              : 
     184           19 : CHIP_ERROR DefaultSessionResumptionStorage::DeleteAll(FabricIndex fabricIndex)
     185              : {
     186           19 :     CHIP_ERROR stickyErr = CHIP_NO_ERROR;
     187           19 :     size_t found         = 0;
     188           19 :     SessionIndex index;
     189           19 :     ReturnErrorOnFailure(LoadIndex(index));
     190           19 :     size_t initialSize = index.mSize;
     191          433 :     for (size_t i = 0; i < initialSize; ++i)
     192              :     {
     193          414 :         CHIP_ERROR err = CHIP_NO_ERROR;
     194          414 :         size_t cur     = i - found;
     195          414 :         size_t remain  = initialSize - i;
     196              :         ResumptionIdStorage resumptionId;
     197          414 :         Crypto::P256ECDHDerivedSecret sharedSecret;
     198          414 :         CATValues peerCATs;
     199          414 :         if (index.mNodes[cur].GetFabricIndex() != fabricIndex)
     200              :         {
     201          363 :             continue;
     202              :         }
     203           51 :         err       = LoadState(index.mNodes[cur], resumptionId, sharedSecret, peerCATs);
     204           51 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     205           51 :         if (err != CHIP_NO_ERROR)
     206              :         {
     207            0 :             ChipLogError(SecureChannel,
     208              :                          "Session resumption cache deletion partially failed for fabric index %u, "
     209              :                          "unable to load node state: %" CHIP_ERROR_FORMAT,
     210              :                          fabricIndex, err.Format());
     211            0 :             continue;
     212              :         }
     213           51 :         err       = DeleteLink(resumptionId);
     214           51 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     215           51 :         if (err != CHIP_NO_ERROR)
     216              :         {
     217            0 :             ChipLogError(SecureChannel,
     218              :                          "Session resumption cache deletion partially failed for fabric index %u, "
     219              :                          "unable to delete node link: %" CHIP_ERROR_FORMAT,
     220              :                          fabricIndex, err.Format());
     221            0 :             continue;
     222              :         }
     223           51 :         err       = DeleteState(index.mNodes[cur]);
     224           51 :         stickyErr = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     225           51 :         if (err != CHIP_NO_ERROR)
     226              :         {
     227            0 :             ChipLogError(SecureChannel,
     228              :                          "Session resumption cache is in an inconsistent state!  "
     229              :                          "Unable to delete node state during attempted deletion of fabric index %u: %" CHIP_ERROR_FORMAT,
     230              :                          fabricIndex, err.Format());
     231            0 :             continue;
     232              :         }
     233           51 :         ++found;
     234           51 :         --remain;
     235           51 :         if (remain)
     236              :         {
     237           49 :             memmove(&index.mNodes[cur], &index.mNodes[cur + 1], remain * sizeof(index.mNodes[0]));
     238              :         }
     239          414 :     }
     240           19 :     if (found)
     241              :     {
     242           19 :         index.mSize -= found;
     243           19 :         CHIP_ERROR err = SaveIndex(index);
     244           19 :         stickyErr      = stickyErr == CHIP_NO_ERROR ? err : stickyErr;
     245           19 :         if (err != CHIP_NO_ERROR)
     246              :         {
     247            0 :             ChipLogError(
     248              :                 SecureChannel,
     249              :                 "Session resumption cache is in an inconsistent state!  "
     250              :                 "Unable to save session resumption index during attempted deletion of fabric index %u: %" CHIP_ERROR_FORMAT,
     251              :                 fabricIndex, err.Format());
     252              :         }
     253              :     }
     254           19 :     return stickyErr;
     255              : }
     256              : 
     257              : } // namespace chip
        

Generated by: LCOV version 2.0-1