Matter SDK Coverage Report
Current view: top level - protocols/secure_channel - PairingSession.h (source / functions) Coverage Total Hit
Test: SHA:ddf6e2f45615ec92d7332ac2c18a835c77f6ab80 Lines: 87.1 % 62 54
Test Date: 2025-01-28 08:09:57 Functions: 68.8 % 16 11

            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           34 :     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              : 
     133            9 :     void SetRemoteSessionParameters(const SessionParameters & sessionParams) { mRemoteSessionParams = sessionParams; }
     134              : 
     135            0 :     virtual void OnSuccessStatusReport() {}
     136              : 
     137              :     // Handle a failure StatusReport message from the server.  protocolData will
     138              :     // depend on exactly what the generalCode/protocolCode are.
     139            0 :     virtual CHIP_ERROR OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode,
     140              :                                              Optional<uintptr_t> protocolData)
     141              :     {
     142            0 :         return CHIP_ERROR_INTERNAL;
     143              :     }
     144              : 
     145           15 :     void SendStatusReport(Optional<Messaging::ExchangeHandle> & exchangeCtxt, uint16_t protocolCode)
     146              :     {
     147           15 :         Protocols::SecureChannel::GeneralStatusCode generalCode = (protocolCode == Protocols::SecureChannel::kProtocolCodeSuccess)
     148           15 :             ? Protocols::SecureChannel::GeneralStatusCode::kSuccess
     149              :             : Protocols::SecureChannel::GeneralStatusCode::kFailure;
     150              : 
     151           15 :         ChipLogDetail(SecureChannel, "Sending status report. Protocol code %d, exchange %d", protocolCode,
     152              :                       exchangeCtxt.Value()->GetExchangeId());
     153              : 
     154           15 :         Protocols::SecureChannel::StatusReport statusReport(generalCode, Protocols::SecureChannel::Id, protocolCode);
     155              : 
     156           15 :         auto handle = System::PacketBufferHandle::New(statusReport.Size());
     157           15 :         VerifyOrReturn(!handle.IsNull(), ChipLogError(SecureChannel, "Failed to allocate status report message"));
     158           15 :         Encoding::LittleEndian::PacketBufferWriter bbuf(std::move(handle));
     159              : 
     160           15 :         statusReport.WriteToBuffer(bbuf);
     161              : 
     162           15 :         System::PacketBufferHandle msg = bbuf.Finalize();
     163           15 :         VerifyOrReturn(!msg.IsNull(), ChipLogError(SecureChannel, "Failed to allocate status report message"));
     164              : 
     165           15 :         CHIP_ERROR err = exchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::StatusReport, std::move(msg));
     166           15 :         if (err != CHIP_NO_ERROR)
     167              :         {
     168            0 :             ChipLogError(SecureChannel, "Failed to send status report message: %" CHIP_ERROR_FORMAT, err.Format());
     169              :         }
     170           15 :     }
     171              : 
     172           15 :     CHIP_ERROR HandleStatusReport(System::PacketBufferHandle && msg, bool successExpected)
     173              :     {
     174           15 :         Protocols::SecureChannel::StatusReport report;
     175           15 :         ReturnErrorOnFailure(report.Parse(std::move(msg)));
     176           15 :         VerifyOrReturnError(report.GetProtocolId() == Protocols::SecureChannel::Id, CHIP_ERROR_INVALID_ARGUMENT);
     177              : 
     178           28 :         if (report.GetGeneralCode() == Protocols::SecureChannel::GeneralStatusCode::kSuccess &&
     179           28 :             report.GetProtocolCode() == Protocols::SecureChannel::kProtocolCodeSuccess && successExpected)
     180              :         {
     181           13 :             OnSuccessStatusReport();
     182           13 :             return CHIP_NO_ERROR;
     183              :         }
     184              : 
     185            2 :         Optional<uintptr_t> protocolData;
     186            3 :         if (report.GetGeneralCode() == Protocols::SecureChannel::GeneralStatusCode::kBusy &&
     187            1 :             report.GetProtocolCode() == Protocols::SecureChannel::kProtocolCodeBusy)
     188              :         {
     189            1 :             if (!report.GetProtocolData().IsNull())
     190              :             {
     191            1 :                 Encoding::LittleEndian::Reader reader(report.GetProtocolData()->Start(), report.GetProtocolData()->DataLength());
     192              : 
     193            1 :                 uint16_t minimumWaitTime = 0;
     194            1 :                 CHIP_ERROR waitTimeErr   = reader.Read16(&minimumWaitTime).StatusCode();
     195            1 :                 if (waitTimeErr != CHIP_NO_ERROR)
     196              :                 {
     197            0 :                     ChipLogError(SecureChannel, "Failed to read the minimum wait time: %" CHIP_ERROR_FORMAT, waitTimeErr.Format());
     198              :                 }
     199              :                 else
     200              :                 {
     201            1 :                     ChipLogProgress(SecureChannel, "Received busy status report with minimum wait time: %u ms", minimumWaitTime);
     202            1 :                     protocolData.Emplace(minimumWaitTime);
     203              :                 }
     204              :             }
     205              :         }
     206              : 
     207              :         // It's very important that we propagate the return value from
     208              :         // OnFailureStatusReport out to the caller.  Make sure we return it directly.
     209            2 :         return OnFailureStatusReport(report.GetGeneralCode(), report.GetProtocolCode(), protocolData);
     210           15 :     }
     211              : 
     212              :     /**
     213              :      * Try to decode the current element (pointed by the TLV reader) as Session parameters (which include MRP parameters).
     214              :      * If the Session parameters are found, outparam sessionParameters is updated with the decoded values.
     215              :      *
     216              :      * Session parameters are optional. So, if the TLV reader is not pointing to the Session parameters,
     217              :      * the function is a noop.
     218              :      *
     219              :      * If the parameters are present, but TLV reader fails to correctly parse it, the function will
     220              :      * return the corresponding error.
     221              :      */
     222              :     static CHIP_ERROR DecodeSessionParametersIfPresent(TLV::Tag expectedTag, TLV::ContiguousBufferTLVReader & tlvReader,
     223              :                                                        SessionParameters & sessionParameters);
     224              : 
     225              :     bool IsSessionEstablishmentInProgress();
     226              : 
     227              :     // TODO: remove Clear, we should create a new instance instead reset the old instance.
     228              :     void Clear();
     229              : 
     230              :     /**
     231              :      * Notify our delegate about a session establishment error and the stage when the error occurs
     232              :      * if we have not already notified it of an error or success before.
     233              :      *
     234              :      * @param error The error code to report.
     235              :      * @param stage The stage of the session when the error occurs, defaults to kNotInKeyExchange.
     236              :      */
     237              :     void NotifySessionEstablishmentError(CHIP_ERROR error,
     238              :                                          SessionEstablishmentStage stage = SessionEstablishmentStage::kNotInKeyExchange);
     239              : 
     240              : protected:
     241              :     CryptoContext::SessionRole mRole;
     242              :     SessionHolderWithDelegate mSecureSessionHolder;
     243              :     // mSessionManager is set if we actually allocate a secure session, so we
     244              :     // can clean it up later as needed.
     245              :     SessionManager * mSessionManager                  = nullptr;
     246              :     Optional<Messaging::ExchangeHandle> mExchangeCtxt = NullOptional;
     247              :     SessionEstablishmentDelegate * mDelegate          = nullptr;
     248              : 
     249              :     // mLocalMRPConfig is our config which is sent to the other end and used by the peer session.
     250              :     // mRemoteSessionParams is received from other end and set to our session.
     251              :     // It is set the first time that session establishment is initiated.
     252              :     Optional<ReliableMessageProtocolConfig> mLocalMRPConfig;
     253              :     SessionParameters mRemoteSessionParams;
     254              : 
     255              : private:
     256              :     Optional<uint16_t> mPeerSessionId;
     257              : };
     258              : 
     259              : } // namespace chip
        

Generated by: LCOV version 2.0-1