LCOV - code coverage report
Current view: top level - protocols/secure_channel - SimpleSessionResumptionStorage.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 116 118 98.3 %
Date: 2024-02-15 08:20:41 Functions: 10 10 100.0 %

          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             : /**
      19             :  *    @file
      20             :  *      This file defines the CHIP CASE Session object that provides
      21             :  *      APIs for constructing a secure session using a certificate from the device's
      22             :  *      operational credentials.
      23             :  */
      24             : 
      25             : #include <protocols/secure_channel/SimpleSessionResumptionStorage.h>
      26             : 
      27             : #include <lib/support/Base64.h>
      28             : #include <lib/support/SafeInt.h>
      29             : 
      30             : namespace chip {
      31             : 
      32             : constexpr TLV::Tag SimpleSessionResumptionStorage::kFabricIndexTag;
      33             : constexpr TLV::Tag SimpleSessionResumptionStorage::kPeerNodeIdTag;
      34             : constexpr TLV::Tag SimpleSessionResumptionStorage::kResumptionIdTag;
      35             : constexpr TLV::Tag SimpleSessionResumptionStorage::kSharedSecretTag;
      36             : constexpr TLV::Tag SimpleSessionResumptionStorage::kCATTag;
      37             : 
      38         883 : StorageKeyName SimpleSessionResumptionStorage::GetStorageKey(const ScopedNodeId & node)
      39             : {
      40         883 :     return DefaultStorageKeyAllocator::FabricSession(node.GetFabricIndex(), node.GetNodeId());
      41             : }
      42             : 
      43         683 : StorageKeyName SimpleSessionResumptionStorage::GetStorageKey(ConstResumptionIdView resumptionId)
      44             : {
      45             :     char resumptionIdBase64[BASE64_ENCODED_LEN(resumptionId.size()) + 1];
      46         683 :     auto len                = Base64Encode(resumptionId.data(), resumptionId.size(), resumptionIdBase64);
      47         683 :     resumptionIdBase64[len] = '\0';
      48         683 :     return DefaultStorageKeyAllocator::SessionResumption(resumptionIdBase64);
      49             : }
      50             : 
      51         216 : CHIP_ERROR SimpleSessionResumptionStorage::SaveIndex(const SessionIndex & index)
      52             : {
      53             :     std::array<uint8_t, MaxIndexSize()> buf;
      54         216 :     TLV::TLVWriter writer;
      55         216 :     writer.Init(buf);
      56             : 
      57             :     TLV::TLVType arrayType;
      58         216 :     ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));
      59             : 
      60        5336 :     for (size_t i = 0; i < index.mSize; ++i)
      61             :     {
      62             :         TLV::TLVType innerType;
      63        5120 :         ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, innerType));
      64        5120 :         ReturnErrorOnFailure(writer.Put(kFabricIndexTag, index.mNodes[i].GetFabricIndex()));
      65        5120 :         ReturnErrorOnFailure(writer.Put(kPeerNodeIdTag, index.mNodes[i].GetNodeId()));
      66        5120 :         ReturnErrorOnFailure(writer.EndContainer(innerType));
      67             :     }
      68             : 
      69         216 :     ReturnErrorOnFailure(writer.EndContainer(arrayType));
      70             : 
      71         216 :     const auto len = writer.GetLengthWritten();
      72         216 :     VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);
      73             : 
      74         216 :     ReturnErrorOnFailure(mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::SessionResumptionIndex().KeyName(), buf.data(),
      75             :                                                    static_cast<uint16_t>(len)));
      76             : 
      77         216 :     return CHIP_NO_ERROR;
      78             : }
      79             : 
      80         275 : CHIP_ERROR SimpleSessionResumptionStorage::LoadIndex(SessionIndex & index)
      81             : {
      82             :     std::array<uint8_t, MaxIndexSize()> buf;
      83         275 :     uint16_t len = static_cast<uint16_t>(buf.size());
      84             : 
      85         275 :     if (mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::SessionResumptionIndex().KeyName(), buf.data(), len) != CHIP_NO_ERROR)
      86             :     {
      87           4 :         index.mSize = 0;
      88           4 :         return CHIP_NO_ERROR;
      89             :     }
      90             : 
      91         271 :     TLV::ContiguousBufferTLVReader reader;
      92         271 :     reader.Init(buf.data(), len);
      93             : 
      94         271 :     ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
      95             :     TLV::TLVType arrayType;
      96         271 :     ReturnErrorOnFailure(reader.EnterContainer(arrayType));
      97             : 
      98         271 :     size_t count = 0;
      99             :     CHIP_ERROR err;
     100        5565 :     while ((err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())) == CHIP_NO_ERROR)
     101             :     {
     102        5294 :         if (count >= ArraySize(index.mNodes))
     103             :         {
     104           0 :             return CHIP_ERROR_NO_MEMORY;
     105             :         }
     106             : 
     107             :         TLV::TLVType containerType;
     108        5294 :         ReturnErrorOnFailure(reader.EnterContainer(containerType));
     109             : 
     110             :         FabricIndex fabricIndex;
     111        5294 :         ReturnErrorOnFailure(reader.Next(kFabricIndexTag));
     112        5294 :         ReturnErrorOnFailure(reader.Get(fabricIndex));
     113             : 
     114             :         NodeId peerNodeId;
     115        5294 :         ReturnErrorOnFailure(reader.Next(kPeerNodeIdTag));
     116        5294 :         ReturnErrorOnFailure(reader.Get(peerNodeId));
     117             : 
     118        5294 :         index.mNodes[count++] = ScopedNodeId(peerNodeId, fabricIndex);
     119             : 
     120        5294 :         ReturnErrorOnFailure(reader.ExitContainer(containerType));
     121             :     }
     122             : 
     123         271 :     if (err != CHIP_END_OF_TLV)
     124             :     {
     125           0 :         return err;
     126             :     }
     127             : 
     128         271 :     ReturnErrorOnFailure(reader.ExitContainer(arrayType));
     129         271 :     ReturnErrorOnFailure(reader.VerifyEndOfContainer());
     130             : 
     131         271 :     index.mSize = count;
     132             : 
     133         271 :     return CHIP_NO_ERROR;
     134             : }
     135             : 
     136         207 : CHIP_ERROR SimpleSessionResumptionStorage::SaveLink(ConstResumptionIdView resumptionId, const ScopedNodeId & node)
     137             : {
     138             :     // Save a link from resumptionId to node, in key: /g/s/<resumptionId>
     139             :     std::array<uint8_t, MaxScopedNodeIdSize()> buf;
     140         207 :     TLV::TLVWriter writer;
     141         207 :     writer.Init(buf);
     142             : 
     143             :     TLV::TLVType outerType;
     144         207 :     ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
     145         207 :     ReturnErrorOnFailure(writer.Put(kFabricIndexTag, node.GetFabricIndex()));
     146         207 :     ReturnErrorOnFailure(writer.Put(kPeerNodeIdTag, node.GetNodeId()));
     147         207 :     ReturnErrorOnFailure(writer.EndContainer(outerType));
     148             : 
     149         207 :     const auto len = writer.GetLengthWritten();
     150         207 :     VerifyOrDie(CanCastTo<uint16_t>(len));
     151             : 
     152         207 :     ReturnErrorOnFailure(mStorage->SyncSetKeyValue(GetStorageKey(resumptionId).KeyName(), buf.data(), static_cast<uint16_t>(len)));
     153         207 :     return CHIP_NO_ERROR;
     154             : }
     155             : 
     156         163 : CHIP_ERROR SimpleSessionResumptionStorage::LoadLink(ConstResumptionIdView resumptionId, ScopedNodeId & node)
     157             : {
     158             :     std::array<uint8_t, MaxScopedNodeIdSize()> buf;
     159         163 :     uint16_t len = static_cast<uint16_t>(buf.size());
     160             : 
     161         163 :     ReturnErrorOnFailure(mStorage->SyncGetKeyValue(GetStorageKey(resumptionId).KeyName(), buf.data(), len));
     162             : 
     163          56 :     TLV::ContiguousBufferTLVReader reader;
     164          56 :     reader.Init(buf.data(), len);
     165             : 
     166          56 :     ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
     167             :     TLV::TLVType containerType;
     168          56 :     ReturnErrorOnFailure(reader.EnterContainer(containerType));
     169             : 
     170             :     FabricIndex fabricIndex;
     171          56 :     ReturnErrorOnFailure(reader.Next(kFabricIndexTag));
     172          56 :     ReturnErrorOnFailure(reader.Get(fabricIndex));
     173             : 
     174             :     NodeId peerNodeId;
     175          56 :     ReturnErrorOnFailure(reader.Next(kPeerNodeIdTag));
     176          56 :     ReturnErrorOnFailure(reader.Get(peerNodeId));
     177             : 
     178          56 :     ReturnErrorOnFailure(reader.ExitContainer(containerType));
     179          56 :     ReturnErrorOnFailure(reader.VerifyEndOfContainer());
     180             : 
     181          56 :     node = ScopedNodeId(peerNodeId, fabricIndex);
     182             : 
     183          56 :     return CHIP_NO_ERROR;
     184             : }
     185             : 
     186         159 : CHIP_ERROR SimpleSessionResumptionStorage::DeleteLink(ConstResumptionIdView resumptionId)
     187             : {
     188         159 :     ReturnErrorOnFailure(mStorage->SyncDeleteKeyValue(GetStorageKey(resumptionId).KeyName()));
     189         159 :     return CHIP_NO_ERROR;
     190             : }
     191             : 
     192         208 : CHIP_ERROR SimpleSessionResumptionStorage::SaveState(const ScopedNodeId & node, ConstResumptionIdView resumptionId,
     193             :                                                      const Crypto::P256ECDHDerivedSecret & sharedSecret, const CATValues & peerCATs)
     194             : {
     195             :     // Save session state into key: /f/<fabricIndex>/s/<nodeId>
     196             :     std::array<uint8_t, MaxStateSize()> buf;
     197         208 :     TLV::TLVWriter writer;
     198         208 :     writer.Init(buf);
     199             : 
     200             :     TLV::TLVType outerType;
     201         208 :     ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
     202             : 
     203         208 :     ReturnErrorOnFailure(writer.Put(kResumptionIdTag, resumptionId));
     204             : 
     205         208 :     ReturnErrorOnFailure(writer.Put(kSharedSecretTag, ByteSpan(sharedSecret.ConstBytes(), sharedSecret.Length())));
     206             : 
     207             :     CATValues::Serialized cat;
     208         208 :     peerCATs.Serialize(cat);
     209         208 :     ReturnErrorOnFailure(writer.Put(kCATTag, ByteSpan(cat)));
     210             : 
     211         208 :     ReturnErrorOnFailure(writer.EndContainer(outerType));
     212             : 
     213         208 :     const auto len = writer.GetLengthWritten();
     214         208 :     VerifyOrDie(CanCastTo<uint16_t>(len));
     215             : 
     216         208 :     ReturnErrorOnFailure(mStorage->SyncSetKeyValue(GetStorageKey(node).KeyName(), buf.data(), static_cast<uint16_t>(len)));
     217         208 :     return CHIP_NO_ERROR;
     218             : }
     219             : 
     220         474 : CHIP_ERROR SimpleSessionResumptionStorage::LoadState(const ScopedNodeId & node, ResumptionIdStorage & resumptionId,
     221             :                                                      Crypto::P256ECDHDerivedSecret & sharedSecret, CATValues & peerCATs)
     222             : {
     223             :     std::array<uint8_t, MaxStateSize()> buf;
     224         474 :     uint16_t len = static_cast<uint16_t>(buf.size());
     225             : 
     226         474 :     ReturnErrorOnFailure(mStorage->SyncGetKeyValue(GetStorageKey(node).KeyName(), buf.data(), len));
     227             : 
     228         318 :     TLV::ContiguousBufferTLVReader reader;
     229         318 :     reader.Init(buf.data(), len);
     230             : 
     231         318 :     ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
     232             :     TLV::TLVType containerType;
     233         318 :     ReturnErrorOnFailure(reader.EnterContainer(containerType));
     234             : 
     235         318 :     ByteSpan resumptionIdSpan;
     236         318 :     ReturnErrorOnFailure(reader.Next(kResumptionIdTag));
     237         318 :     ReturnErrorOnFailure(reader.Get(resumptionIdSpan));
     238         318 :     VerifyOrReturnError(resumptionIdSpan.size() == resumptionId.size(), CHIP_ERROR_KEY_NOT_FOUND);
     239         318 :     std::copy(resumptionIdSpan.begin(), resumptionIdSpan.end(), resumptionId.begin());
     240             : 
     241         318 :     ByteSpan sharedSecretSpan;
     242         318 :     ReturnErrorOnFailure(reader.Next(kSharedSecretTag));
     243         318 :     ReturnErrorOnFailure(reader.Get(sharedSecretSpan));
     244         318 :     VerifyOrReturnError(sharedSecretSpan.size() <= sharedSecret.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
     245         318 :     ::memcpy(sharedSecret.Bytes(), sharedSecretSpan.data(), sharedSecretSpan.size());
     246         318 :     sharedSecret.SetLength(sharedSecretSpan.size());
     247             : 
     248         318 :     ByteSpan catSpan;
     249         318 :     ReturnErrorOnFailure(reader.Next(kCATTag));
     250         318 :     ReturnErrorOnFailure(reader.Get(catSpan));
     251             :     CATValues::Serialized cat;
     252         318 :     VerifyOrReturnError(sizeof(cat) == catSpan.size(), CHIP_ERROR_INVALID_TLV_ELEMENT);
     253         318 :     ::memcpy(cat, catSpan.data(), catSpan.size());
     254         318 :     peerCATs.Deserialize(cat);
     255             : 
     256         318 :     ReturnErrorOnFailure(reader.ExitContainer(containerType));
     257         318 :     ReturnErrorOnFailure(reader.VerifyEndOfContainer());
     258             : 
     259         318 :     return CHIP_NO_ERROR;
     260             : }
     261             : 
     262         102 : CHIP_ERROR SimpleSessionResumptionStorage::DeleteState(const ScopedNodeId & node)
     263             : {
     264         102 :     ReturnErrorOnFailure(mStorage->SyncDeleteKeyValue(GetStorageKey(node).KeyName()));
     265         102 :     return CHIP_NO_ERROR;
     266             : }
     267             : 
     268             : } // namespace chip

Generated by: LCOV version 1.14