Matter SDK Coverage Report
Current view: top level - transport - SecureSession.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 89.0 % 91 81
Test Date: 2025-01-17 19:00:11 Functions: 94.6 % 37 35

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       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              :  * @brief Defines state relevant for an active connection to a peer.
      20              :  */
      21              : 
      22              : #pragma once
      23              : 
      24              : #include <app/util/basic-types.h>
      25              : #include <ble/Ble.h>
      26              : #include <lib/core/ReferenceCounted.h>
      27              : #include <messaging/ReliableMessageProtocolConfig.h>
      28              : #include <transport/CryptoContext.h>
      29              : #include <transport/Session.h>
      30              : #include <transport/SessionMessageCounter.h>
      31              : #include <transport/raw/PeerAddress.h>
      32              : 
      33              : namespace chip {
      34              : namespace Transport {
      35              : 
      36              : class SecureSessionTable;
      37              : class SecureSessionDeleter
      38              : {
      39              : public:
      40              :     static void Release(SecureSession * entry);
      41              : };
      42              : 
      43              : /**
      44              :  * Defines state of a peer connection at a transport layer.
      45              :  *
      46              :  * Information contained within the state:
      47              :  *   - SecureSessionType represents CASE or PASE session
      48              :  *   - PeerAddress represents how to talk to the peer
      49              :  *   - PeerNodeId is the unique ID of the peer
      50              :  *   - PeerCATs represents CASE Authenticated Tags
      51              :  *   - SendMessageIndex is an ever increasing index for sending messages
      52              :  *   - LastActivityTime is a monotonic timestamp of when this connection was
      53              :  *     last used. Inactive connections can expire.
      54              :  *   - CryptoContext contains the encryption context of a connection
      55              :  */
      56              : class SecureSession : public Session, public ReferenceCounted<SecureSession, SecureSessionDeleter, 0, uint16_t>
      57              : {
      58              : public:
      59              :     /**
      60              :      *  @brief
      61              :      *    Defines SecureSession Type. Currently supported types are PASE and CASE.
      62              :      */
      63              :     enum class Type : uint8_t
      64              :     {
      65              :         kPASE = 1,
      66              :         kCASE = 2,
      67              :     };
      68              : 
      69              :     // Test-only: inject a session in Active state.
      70              :     // TODO: Tests should allocate a pending session and then call Activate(), just like non-test code does.
      71         1484 :     SecureSession(SecureSessionTable & table, Type secureSessionType, uint16_t localSessionId, NodeId localNodeId,
      72              :                   NodeId peerNodeId, CATValues peerCATs, uint16_t peerSessionId, FabricIndex fabric,
      73         1484 :                   const ReliableMessageProtocolConfig & config) :
      74         1484 :         mTable(table),
      75         1484 :         mState(State::kEstablishing), mSecureSessionType(secureSessionType), mLocalNodeId(localNodeId), mPeerNodeId(peerNodeId),
      76         1484 :         mPeerCATs(peerCATs), mLocalSessionId(localSessionId), mPeerSessionId(peerSessionId), mRemoteSessionParams(config)
      77              :     {
      78         1484 :         MoveToState(State::kActive);
      79         1484 :         Retain(); // Put the test session in Active state. This ref is released inside MarkForEviction
      80         1484 :         SetFabricIndex(fabric);
      81         1484 :         ChipLogDetail(Inet, "SecureSession[%p]: Allocated for Test Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
      82              :                       mLocalSessionId);
      83         1484 :     }
      84              : 
      85              :     /**
      86              :      * @brief
      87              :      *   Construct a secure session object to associate with a pending secure
      88              :      *   session establishment attempt.  The object for the pending session
      89              :      *   receives a local session ID, but no other state.
      90              :      */
      91       133750 :     SecureSession(SecureSessionTable & table, Type secureSessionType, uint16_t localSessionId) :
      92       133750 :         mTable(table), mState(State::kEstablishing), mSecureSessionType(secureSessionType), mLocalSessionId(localSessionId)
      93              :     {
      94       133750 :         ChipLogDetail(Inet, "SecureSession[%p]: Allocated Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
      95              :                       mLocalSessionId);
      96       133750 :     }
      97              : 
      98              :     /**
      99              :      * @brief
     100              :      *   Activate a pending Secure Session that had been reserved during CASE or
     101              :      *   PASE, setting internal state according to the parameters used and
     102              :      *   discovered during session establishment.
     103              :      */
     104              :     void Activate(const ScopedNodeId & localNode, const ScopedNodeId & peerNode, CATValues peerCATs, uint16_t peerSessionId,
     105              :                   const SessionParameters & sessionParameters);
     106              : 
     107       135234 :     ~SecureSession() override
     108       135234 :     {
     109       135234 :         ChipLogDetail(Inet, "SecureSession[%p]: Released - Type:%d LSID:%d", this, to_underlying(mSecureSessionType),
     110              :                       mLocalSessionId);
     111       135234 :     }
     112              : 
     113              :     SecureSession(SecureSession &&)                  = delete;
     114              :     SecureSession(const SecureSession &)             = delete;
     115              :     SecureSession & operator=(const SecureSession &) = delete;
     116              :     SecureSession & operator=(SecureSession &&)      = delete;
     117              : 
     118              :     void Retain() override;
     119              :     void Release() override;
     120              : 
     121        21632 :     bool IsActiveSession() const override { return mState == State::kActive; }
     122           56 :     bool IsEstablishing() const { return mState == State::kEstablishing; }
     123           16 :     bool IsPendingEviction() const { return mState == State::kPendingEviction; }
     124         9758 :     bool IsDefunct() const { return mState == State::kDefunct; }
     125           84 :     const char * GetStateStr() const { return StateToString(mState); }
     126              : 
     127              :     /*
     128              :      * This marks the session for eviction. It will first detach all SessionHolders attached to this
     129              :      * session by calling 'OnSessionReleased' on each of them. This will force them to release their reference
     130              :      * to the session. If there are no more references left, the session will then be de-allocated.
     131              :      *
     132              :      * Once marked for eviction, the session SHALL NOT ever become active again.
     133              :      *
     134              :      */
     135              :     void MarkForEviction();
     136              : 
     137              :     /*
     138              :      * This marks a previously active session as defunct to temporarily prevent it from being used with
     139              :      * new exchanges to send or receive messages on this session. This should be called when there is suspicion of
     140              :      * a loss-of-sync with the session state on the associated peer. This could arise if there is evidence
     141              :      * of transport failure.
     142              :      *
     143              :      * If messages are received thereafter on this session, the session SHALL be put back into the Active state.
     144              :      *
     145              :      * This SHALL only be callable on an active session.
     146              :      * This SHALL NOT detach any existing SessionHolders.
     147              :      *
     148              :      */
     149              :     void MarkAsDefunct();
     150              : 
     151       574056 :     Session::SessionType GetSessionType() const override { return Session::SessionType::kSecure; }
     152              : 
     153        22020 :     ScopedNodeId GetPeer() const override { return ScopedNodeId(mPeerNodeId, GetFabricIndex()); }
     154              : 
     155         9726 :     ScopedNodeId GetLocalScopedNodeId() const override { return ScopedNodeId(mLocalNodeId, GetFabricIndex()); }
     156              : 
     157              :     Access::SubjectDescriptor GetSubjectDescriptor() const override;
     158              : 
     159              :     bool IsCommissioningSession() const override;
     160              : 
     161        40345 :     bool AllowsMRP() const override
     162              :     {
     163        40556 :         return ((GetPeerAddress().GetTransportType() == Transport::Type::kUdp) ||
     164        40556 :                 (GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF));
     165              :     }
     166              : 
     167        11661 :     bool AllowsLargePayload() const override { return GetPeerAddress().GetTransportType() == Transport::Type::kTcp; }
     168              : 
     169         6429 :     System::Clock::Milliseconds32 GetAckTimeout() const override
     170              :     {
     171         6429 :         switch (mPeerAddress.GetTransportType())
     172              :         {
     173         6382 :         case Transport::Type::kUdp: {
     174         6382 :             const ReliableMessageProtocolConfig & remoteMRPConfig = mRemoteSessionParams.GetMRPConfig();
     175         6382 :             return GetRetransmissionTimeout(remoteMRPConfig.mActiveRetransTimeout, remoteMRPConfig.mIdleRetransTimeout,
     176        12764 :                                             GetLastPeerActivityTime(), remoteMRPConfig.mActiveThresholdTime);
     177              :         }
     178            0 :         case Transport::Type::kTcp:
     179            0 :             return System::Clock::Seconds16(30);
     180            0 :         case Transport::Type::kBle:
     181            0 :             return System::Clock::Milliseconds32(BTP_ACK_TIMEOUT_MS);
     182           47 :         default:
     183           47 :             break;
     184              :         }
     185           47 :         return System::Clock::Timeout();
     186              :     }
     187              : 
     188         6741 :     System::Clock::Milliseconds32 GetMessageReceiptTimeout(System::Clock::Timestamp ourLastActivity) const override
     189              :     {
     190         6741 :         switch (mPeerAddress.GetTransportType())
     191              :         {
     192         6694 :         case Transport::Type::kUdp: {
     193         6694 :             const auto & maybeLocalMRPConfig = GetLocalMRPConfig();
     194         6694 :             const auto & defaultMRRPConfig   = GetDefaultMRPConfig();
     195         6694 :             const auto & localMRPConfig      = maybeLocalMRPConfig.ValueOr(defaultMRRPConfig);
     196         6694 :             return GetRetransmissionTimeout(localMRPConfig.mActiveRetransTimeout, localMRPConfig.mIdleRetransTimeout,
     197        13388 :                                             ourLastActivity, localMRPConfig.mActiveThresholdTime);
     198         6694 :         }
     199            0 :         case Transport::Type::kTcp:
     200            0 :             return System::Clock::Seconds16(30);
     201            0 :         case Transport::Type::kBle:
     202            0 :             return System::Clock::Milliseconds32(BTP_ACK_TIMEOUT_MS);
     203           47 :         default:
     204           47 :             break;
     205              :         }
     206           47 :         return System::Clock::Timeout();
     207              :     }
     208              : 
     209        81330 :     const PeerAddress & GetPeerAddress() const { return mPeerAddress; }
     210         1476 :     void SetPeerAddress(const PeerAddress & address) { mPeerAddress = address; }
     211              : 
     212        27170 :     Type GetSecureSessionType() const { return mSecureSessionType; }
     213         9659 :     bool IsCASESession() const { return GetSecureSessionType() == Type::kCASE; }
     214         7484 :     bool IsPASESession() const { return GetSecureSessionType() == Type::kPASE; }
     215        18390 :     NodeId GetPeerNodeId() const { return mPeerNodeId; }
     216         9616 :     NodeId GetLocalNodeId() const { return mLocalNodeId; }
     217              : 
     218          106 :     const CATValues & GetPeerCATs() const { return mPeerCATs; }
     219              : 
     220              :     void SetRemoteSessionParameters(const SessionParameters & sessionParams) { mRemoteSessionParams = sessionParams; }
     221              : 
     222        26182 :     const SessionParameters & GetRemoteSessionParameters() const override { return mRemoteSessionParams; }
     223              : 
     224        43176 :     uint16_t GetLocalSessionId() const { return mLocalSessionId; }
     225         9724 :     uint16_t GetPeerSessionId() const { return mPeerSessionId; }
     226              : 
     227              :     // Called when AddNOC has gone through sufficient success that we need to switch the
     228              :     // session to reflect a new fabric if it was a PASE session
     229              :     CHIP_ERROR AdoptFabricIndex(FabricIndex fabricIndex)
     230              :     {
     231              :         // It's not legal to augment session type for non-PASE
     232              :         if (mSecureSessionType != Type::kPASE)
     233              :         {
     234              :             return CHIP_ERROR_INVALID_ARGUMENT;
     235              :         }
     236              :         SetFabricIndex(fabricIndex);
     237              :         return CHIP_NO_ERROR;
     238              :     }
     239              : 
     240          282 :     System::Clock::Timestamp GetLastActivityTime() const { return mLastActivityTime; }
     241        16139 :     System::Clock::Timestamp GetLastPeerActivityTime() const { return mLastPeerActivityTime; }
     242        19469 :     void MarkActive() { mLastActivityTime = System::SystemClock().GetMonotonicTimestamp(); }
     243         9740 :     void MarkActiveRx()
     244              :     {
     245         9740 :         mLastPeerActivityTime = System::SystemClock().GetMonotonicTimestamp();
     246         9740 :         MarkActive();
     247              : 
     248         9740 :         if (mState == State::kDefunct)
     249              :         {
     250            0 :             MoveToState(State::kActive);
     251              :         }
     252         9740 :     }
     253              : 
     254            8 :     void SetCaseCommissioningSessionStatus(bool isCaseCommissioningSession)
     255              :     {
     256            8 :         VerifyOrDie(GetSecureSessionType() == Type::kCASE);
     257            8 :         mIsCaseCommissioningSession = isCaseCommissioningSession;
     258            8 :     }
     259              : 
     260         9750 :     bool IsPeerActive() const
     261              :     {
     262        19500 :         return ((System::SystemClock().GetMonotonicTimestamp() - GetLastPeerActivityTime()) <
     263        19500 :                 GetRemoteMRPConfig().mActiveThresholdTime);
     264              :     }
     265              : 
     266         1690 :     System::Clock::Timestamp GetMRPBaseTimeout() const override
     267              :     {
     268         1690 :         return IsPeerActive() ? GetRemoteMRPConfig().mActiveRetransTimeout : GetRemoteMRPConfig().mIdleRetransTimeout;
     269              :     }
     270              : 
     271        20815 :     CryptoContext & GetCryptoContext() { return mCryptoContext; }
     272              : 
     273            0 :     const CryptoContext & GetCryptoContext() const { return mCryptoContext; }
     274              : 
     275        30349 :     SessionMessageCounter & GetSessionMessageCounter() { return mSessionMessageCounter; }
     276              : 
     277              :     // This should be a private API, only meant to be called by SecureSessionTable
     278              :     // Session holders to this session may shift to the target session regarding SessionDelegate::GetNewSessionHandlingPolicy.
     279              :     // It requires that the target sessoin is also a CASE session, having the same peer and CATs as this session.
     280              :     void NewerSessionAvailable(const SessionHandle & session);
     281              : 
     282              : private:
     283              :     enum class State : uint8_t
     284              :     {
     285              :         //
     286              :         // Denotes a secure session object that is internally
     287              :         // reserved by the stack before and during session establishment.
     288              :         //
     289              :         // Although the stack can tolerate eviction of these (releasing one
     290              :         // out from under the holder would exhibit as CHIP_ERROR_INCORRECT_STATE
     291              :         // during CASE or PASE), intent is that we should not and would leave
     292              :         // these untouched until CASE or PASE complete.
     293              :         //
     294              :         // In this state, the reference count is held by the PairingSession.
     295              :         //
     296              :         kEstablishing = 1,
     297              : 
     298              :         //
     299              :         // The session is active, ready for use. When transitioning to this state via Activate, the
     300              :         // reference count is incremented by 1, and will subsequently be decremented
     301              :         // by 1 when MarkForEviction is called. This ensures the session remains resident
     302              :         // and active for future use even if there currently are no references to it.
     303              :         //
     304              :         kActive = 2,
     305              : 
     306              :         //
     307              :         // The session is temporarily disabled due to suspicion of a loss of synchronization
     308              :         // with the session state on the peer (e.g transport failure).
     309              :         // In this state, no new outbound exchanges can be created. However, if we receive valid messages
     310              :         // again on this session, we CAN mark this session as being active again.
     311              :         //
     312              :         // Transitioning to this state does not detach any existing SessionHolders.
     313              :         //
     314              :         // In addition to any existing SessionHolders holding a reference to this session, the SessionManager
     315              :         // maintains a reference as well to the session that will only be relinquished when MarkForEviction is called.
     316              :         //
     317              :         kDefunct = 3,
     318              : 
     319              :         //
     320              :         // The session has been marked for eviction and is pending deallocation. All SessionHolders would have already
     321              :         // been detached in a previous call to MarkForEviction. Future SessionHolders will not be able to attach to
     322              :         // this session.
     323              :         //
     324              :         // When all SessionHandles go out of scope, the session will be released automatically.
     325              :         //
     326              :         kPendingEviction = 4,
     327              :     };
     328              : 
     329              :     const char * StateToString(State state) const;
     330              :     void MoveToState(State targetState);
     331              : 
     332              :     friend class SecureSessionDeleter;
     333              :     friend class TestSecureSessionTable;
     334              : 
     335              :     SecureSessionTable & mTable;
     336              :     State mState;
     337              :     const Type mSecureSessionType;
     338              :     bool mIsCaseCommissioningSession = false;
     339              :     NodeId mLocalNodeId              = kUndefinedNodeId;
     340              :     NodeId mPeerNodeId               = kUndefinedNodeId;
     341              :     CATValues mPeerCATs              = CATValues{};
     342              :     const uint16_t mLocalSessionId;
     343              :     uint16_t mPeerSessionId = 0;
     344              : 
     345              :     PeerAddress mPeerAddress;
     346              : 
     347              :     /// Timestamp of last tx or rx. @see SessionTimestamp in the spec
     348              :     System::Clock::Timestamp mLastActivityTime = System::SystemClock().GetMonotonicTimestamp();
     349              : 
     350              :     /// Timestamp of last rx. @see ActiveTimestamp in the spec
     351              :     System::Clock::Timestamp mLastPeerActivityTime = System::SystemClock().GetMonotonicTimestamp();
     352              : 
     353              :     SessionParameters mRemoteSessionParams;
     354              :     CryptoContext mCryptoContext;
     355              :     SessionMessageCounter mSessionMessageCounter;
     356              : };
     357              : 
     358              : } // namespace Transport
     359              : } // namespace chip
        

Generated by: LCOV version 2.0-1