Matter SDK Coverage Report
Current view: top level - protocols/secure_channel - PairingSession.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 86.9 % 61 53
Test Date: 2025-01-17 19:00:11 Functions: 66.7 % 15 10

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021-2022 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      This file defines a common interface to access various types of secure
      22              :  *      pairing sessions (e.g. PASE, CASE)
      23              :  *
      24              :  */
      25              : 
      26              : #pragma once
      27              : 
      28              : #include <lib/core/CHIPError.h>
      29              : #include <lib/core/Optional.h>
      30              : #include <lib/core/TLV.h>
      31              : #include <messaging/ExchangeContext.h>
      32              : #include <messaging/SessionParameters.h>
      33              : #include <protocols/secure_channel/Constants.h>
      34              : #include <protocols/secure_channel/SessionEstablishmentDelegate.h>
      35              : #include <protocols/secure_channel/StatusReport.h>
      36              : #include <transport/CryptoContext.h>
      37              : #include <transport/SecureSession.h>
      38              : 
      39              : namespace chip {
      40              : 
      41              : class SessionManager;
      42              : 
      43              : class DLL_EXPORT PairingSession : public SessionDelegate
      44              : {
      45              : public:
      46            2 :     PairingSession() : mSecureSessionHolder(*this) {}
      47           50 :     virtual ~PairingSession() { Clear(); }
      48              : 
      49              :     virtual Transport::SecureSession::Type GetSecureSessionType() const = 0;
      50              :     virtual ScopedNodeId GetPeer() const                                = 0;
      51              :     virtual ScopedNodeId GetLocalScopedNodeId() const                   = 0;
      52              :     virtual CATValues GetPeerCATs() const                               = 0;
      53              : 
      54              :     // Implement SessionDelegate
      55            1 :     NewSessionHandlingPolicy GetNewSessionHandlingPolicy() override { return NewSessionHandlingPolicy::kStayAtOldSession; }
      56              :     void OnSessionReleased() override;
      57              : 
      58          112 :     Optional<uint16_t> GetLocalSessionId() const
      59              :     {
      60          112 :         Optional<uint16_t> localSessionId;
      61          112 :         VerifyOrExit(mSecureSessionHolder, localSessionId = NullOptional);
      62          112 :         VerifyOrExit(mSecureSessionHolder->GetSessionType() == Transport::Session::SessionType::kSecure,
      63              :                      localSessionId = Optional<uint16_t>::Missing());
      64          112 :         localSessionId.SetValue(mSecureSessionHolder->AsSecureSession()->GetLocalSessionId());
      65          112 :     exit:
      66          112 :         return localSessionId;
      67              :     }
      68              : 
      69              :     /**
      70              :      * Copy the underlying session (if present) into a SessionHandle that a caller can use to
      71              :      * obtain a reference to the session.
      72              :      */
      73           14 :     Optional<SessionHandle> CopySecureSession()
      74              :     {
      75           14 :         if (mSecureSessionHolder)
      76              :         {
      77           14 :             VerifyOrDie(mSecureSessionHolder->GetSessionType() == Transport::Session::SessionType::kSecure);
      78           14 :             return MakeOptional<SessionHandle>(*mSecureSessionHolder->AsSecureSession());
      79              :         }
      80              : 
      81            0 :         return Optional<SessionHandle>::Missing();
      82              :     }
      83              : 
      84           26 :     uint16_t GetPeerSessionId() const
      85              :     {
      86           26 :         VerifyOrDie(mPeerSessionId.HasValue());
      87           26 :         return mPeerSessionId.Value();
      88              :     }
      89              : 
      90              :     bool IsValidPeerSessionId() const { return mPeerSessionId.HasValue(); }
      91              : 
      92              :     /**
      93              :      * @brief
      94              :      *   Derive a secure session from the paired session. The API will return error if called before pairing is established.
      95              :      *
      96              :      * @param session     Reference to the secure session that will be initialized once pairing is complete
      97              :      * @return CHIP_ERROR The result of session derivation
      98              :      */
      99              :     virtual CHIP_ERROR DeriveSecureSession(CryptoContext & session) = 0;
     100              : 
     101            0 :     const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return mRemoteSessionParams.GetMRPConfig(); }
     102           55 :     const SessionParameters & GetRemoteSessionParameters() const { return mRemoteSessionParams; }
     103            0 :     void SetRemoteMRPConfig(const ReliableMessageProtocolConfig & config) { mRemoteSessionParams.SetMRPConfig(config); }
     104              : 
     105              :     /**
     106              :      * Encode the Session Parameters using the provided TLV tag.
     107              :      */
     108              :     static CHIP_ERROR EncodeSessionParameters(TLV::Tag tag, const ReliableMessageProtocolConfig & mrpLocalConfig,
     109              :                                               TLV::TLVWriter & tlvWriter);
     110              : 
     111              : protected:
     112              :     /**
     113              :      * Allocate a secure session object from the passed session manager for the
     114              :      * pending session establishment operation.
     115              :      *
     116              :      * @param sessionManager        Session manager from which to allocate a secure session object
     117              :      * @param sessionEvictionHint   If we're either establishing or just finished establishing a session to a peer in either
     118              :      * initiator or responder roles, the node id of that peer should be provided in this argument. Else, it should be initialized to
     119              :      * a default-constructed ScopedNodeId().
     120              :      *
     121              :      * @return CHIP_ERROR The outcome of the allocation attempt
     122              :      */
     123              :     CHIP_ERROR AllocateSecureSession(SessionManager & sessionManager, const ScopedNodeId & sessionEvictionHint = ScopedNodeId());
     124              : 
     125              :     CHIP_ERROR ActivateSecureSession(const Transport::PeerAddress & peerAddress);
     126              : 
     127              :     void Finish();
     128              : 
     129              :     void DiscardExchange(); // Clear our reference to our exchange context pointer so that it can close itself at some later time.
     130              : 
     131           30 :     void SetPeerSessionId(uint16_t id) { mPeerSessionId.SetValue(id); }
     132            0 :     virtual void OnSuccessStatusReport() {}
     133              : 
     134              :     // Handle a failure StatusReport message from the server.  protocolData will
     135              :     // depend on exactly what the generalCode/protocolCode are.
     136            0 :     virtual CHIP_ERROR OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode,
     137              :                                              Optional<uintptr_t> protocolData)
     138              :     {
     139            0 :         return CHIP_ERROR_INTERNAL;
     140              :     }
     141              : 
     142           15 :     void SendStatusReport(Optional<Messaging::ExchangeHandle> & exchangeCtxt, uint16_t protocolCode)
     143              :     {
     144           15 :         Protocols::SecureChannel::GeneralStatusCode generalCode = (protocolCode == Protocols::SecureChannel::kProtocolCodeSuccess)
     145           15 :             ? Protocols::SecureChannel::GeneralStatusCode::kSuccess
     146              :             : Protocols::SecureChannel::GeneralStatusCode::kFailure;
     147              : 
     148           15 :         ChipLogDetail(SecureChannel, "Sending status report. Protocol code %d, exchange %d", protocolCode,
     149              :                       exchangeCtxt.Value()->GetExchangeId());
     150              : 
     151           15 :         Protocols::SecureChannel::StatusReport statusReport(generalCode, Protocols::SecureChannel::Id, protocolCode);
     152              : 
     153           15 :         auto handle = System::PacketBufferHandle::New(statusReport.Size());
     154           15 :         VerifyOrReturn(!handle.IsNull(), ChipLogError(SecureChannel, "Failed to allocate status report message"));
     155           15 :         Encoding::LittleEndian::PacketBufferWriter bbuf(std::move(handle));
     156              : 
     157           15 :         statusReport.WriteToBuffer(bbuf);
     158              : 
     159           15 :         System::PacketBufferHandle msg = bbuf.Finalize();
     160           15 :         VerifyOrReturn(!msg.IsNull(), ChipLogError(SecureChannel, "Failed to allocate status report message"));
     161              : 
     162           15 :         CHIP_ERROR err = exchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::StatusReport, std::move(msg));
     163           15 :         if (err != CHIP_NO_ERROR)
     164              :         {
     165            0 :             ChipLogError(SecureChannel, "Failed to send status report message: %" CHIP_ERROR_FORMAT, err.Format());
     166              :         }
     167           15 :     }
     168              : 
     169           15 :     CHIP_ERROR HandleStatusReport(System::PacketBufferHandle && msg, bool successExpected)
     170              :     {
     171           15 :         Protocols::SecureChannel::StatusReport report;
     172           15 :         ReturnErrorOnFailure(report.Parse(std::move(msg)));
     173           15 :         VerifyOrReturnError(report.GetProtocolId() == Protocols::SecureChannel::Id, CHIP_ERROR_INVALID_ARGUMENT);
     174              : 
     175           28 :         if (report.GetGeneralCode() == Protocols::SecureChannel::GeneralStatusCode::kSuccess &&
     176           28 :             report.GetProtocolCode() == Protocols::SecureChannel::kProtocolCodeSuccess && successExpected)
     177              :         {
     178           13 :             OnSuccessStatusReport();
     179           13 :             return CHIP_NO_ERROR;
     180              :         }
     181              : 
     182            2 :         Optional<uintptr_t> protocolData;
     183            3 :         if (report.GetGeneralCode() == Protocols::SecureChannel::GeneralStatusCode::kBusy &&
     184            1 :             report.GetProtocolCode() == Protocols::SecureChannel::kProtocolCodeBusy)
     185              :         {
     186            1 :             if (!report.GetProtocolData().IsNull())
     187              :             {
     188            1 :                 Encoding::LittleEndian::Reader reader(report.GetProtocolData()->Start(), report.GetProtocolData()->DataLength());
     189              : 
     190            1 :                 uint16_t minimumWaitTime = 0;
     191            1 :                 CHIP_ERROR waitTimeErr   = reader.Read16(&minimumWaitTime).StatusCode();
     192            1 :                 if (waitTimeErr != CHIP_NO_ERROR)
     193              :                 {
     194            0 :                     ChipLogError(SecureChannel, "Failed to read the minimum wait time: %" CHIP_ERROR_FORMAT, waitTimeErr.Format());
     195              :                 }
     196              :                 else
     197              :                 {
     198            1 :                     ChipLogProgress(SecureChannel, "Received busy status report with minimum wait time: %u ms", minimumWaitTime);
     199            1 :                     protocolData.Emplace(minimumWaitTime);
     200              :                 }
     201              :             }
     202              :         }
     203              : 
     204              :         // It's very important that we propagate the return value from
     205              :         // OnFailureStatusReport out to the caller.  Make sure we return it directly.
     206            2 :         return OnFailureStatusReport(report.GetGeneralCode(), report.GetProtocolCode(), protocolData);
     207           15 :     }
     208              : 
     209              :     /**
     210              :      * Try to decode the current element (pointed by the TLV reader) as MRP parameters.
     211              :      * If the MRP parameters are found, mRemoteSessionParams is updated with the devoded values.
     212              :      *
     213              :      * MRP parameters are optional. So, if the TLV reader is not pointing to the MRP parameters,
     214              :      * the function is a noop.
     215              :      *
     216              :      * If the parameters are present, but TLV reader fails to correctly parse it, the function will
     217              :      * return the corresponding error.
     218              :      */
     219              :     CHIP_ERROR DecodeMRPParametersIfPresent(TLV::Tag expectedTag, TLV::ContiguousBufferTLVReader & tlvReader);
     220              : 
     221              :     bool IsSessionEstablishmentInProgress();
     222              : 
     223              :     // TODO: remove Clear, we should create a new instance instead reset the old instance.
     224              :     void Clear();
     225              : 
     226              :     /**
     227              :      * Notify our delegate about a session establishment error and the stage when the error occurs
     228              :      * if we have not already notified it of an error or success before.
     229              :      *
     230              :      * @param error The error code to report.
     231              :      * @param stage The stage of the session when the error occurs, defaults to kNotInKeyExchange.
     232              :      */
     233              :     void NotifySessionEstablishmentError(CHIP_ERROR error,
     234              :                                          SessionEstablishmentStage stage = SessionEstablishmentStage::kNotInKeyExchange);
     235              : 
     236              : protected:
     237              :     CryptoContext::SessionRole mRole;
     238              :     SessionHolderWithDelegate mSecureSessionHolder;
     239              :     // mSessionManager is set if we actually allocate a secure session, so we
     240              :     // can clean it up later as needed.
     241              :     SessionManager * mSessionManager                  = nullptr;
     242              :     Optional<Messaging::ExchangeHandle> mExchangeCtxt = NullOptional;
     243              :     SessionEstablishmentDelegate * mDelegate          = nullptr;
     244              : 
     245              :     // mLocalMRPConfig is our config which is sent to the other end and used by the peer session.
     246              :     // mRemoteSessionParams is received from other end and set to our session.
     247              :     // It is set the first time that session establishment is initiated.
     248              :     Optional<ReliableMessageProtocolConfig> mLocalMRPConfig;
     249              :     SessionParameters mRemoteSessionParams;
     250              : 
     251              : private:
     252              :     Optional<uint16_t> mPeerSessionId;
     253              : };
     254              : 
     255              : } // namespace chip
        

Generated by: LCOV version 2.0-1