Update session parameters to be inline with matter 1.3 spec (#30405)

diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn
index a7a9bad..17ce830 100644
--- a/src/app/BUILD.gn
+++ b/src/app/BUILD.gn
@@ -64,6 +64,14 @@
   ]
 }
 
+source_set("revision_info") {
+  sources = [
+    "DataModelRevision.h",
+    "InteractionModelRevision.h",
+    "SpecificationVersion.h",
+  ]
+}
+
 source_set("app_config") {
   sources = [ "AppConfig.h" ]
 
@@ -101,7 +109,6 @@
     "FailSafeContext.h",
     "GlobalAttributes.h",
     "InteractionModelEngine.cpp",
-    "InteractionModelRevision.h",
     "InteractionModelTimeout.h",
     "MessageDef/ArrayBuilder.cpp",
     "MessageDef/ArrayParser.cpp",
@@ -237,6 +244,7 @@
 
   public_deps = [
     ":app_config",
+    ":revision_info",
     "${chip_root}/src/access",
     "${chip_root}/src/app/icd:notifier",
     "${chip_root}/src/app/icd:observer",
diff --git a/src/app/SpecificationVersion.h b/src/app/SpecificationVersion.h
new file mode 100644
index 0000000..b0570da
--- /dev/null
+++ b/src/app/SpecificationVersion.h
@@ -0,0 +1,31 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+/**
+ * CHIP_DEVICE_SPECIFICATION_VERSION
+ *
+ * A number identifying the specification version against which the
+ * Node is certified.
+ *
+ * See section 11.1.5.22. "SpecificationVersion Attribute" in "Service and
+ * Device Management" chapter of the core Matter specification.
+ */
+#ifndef CHIP_DEVICE_SPECIFICATION_VERSION
+#define CHIP_DEVICE_SPECIFICATION_VERSION 0x01030000
+#endif
diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h
index 1a25b18..fb04f9b 100644
--- a/src/lib/core/CHIPConfig.h
+++ b/src/lib/core/CHIPConfig.h
@@ -1601,6 +1601,19 @@
 #endif
 
 /**
+ * @def CHIP_CONFIG_MAX_PATHS_PER_INVOKE
+ *
+ * @brief The maximum number of elements in the InvokeRequests list that the Node is able to process.
+ */
+#ifndef CHIP_CONFIG_MAX_PATHS_PER_INVOKE
+#define CHIP_CONFIG_MAX_PATHS_PER_INVOKE 1
+#endif
+
+#if CHIP_CONFIG_MAX_PATHS_PER_INVOKE < 1 || CHIP_CONFIG_MAX_PATHS_PER_INVOKE > 65535
+#error "CHIP_CONFIG_MAX_PATHS_PER_INVOKE is not allowed to be a number less than 1 or greater than 65535"
+#endif
+
+/**
  * @def CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE
  *
  * @brief Defines the entry iterator delegate pool size of the ICDObserver object pool in ICDManager.h.
diff --git a/src/protocols/secure_channel/BUILD.gn b/src/protocols/secure_channel/BUILD.gn
index 5a24a98..2061b04 100644
--- a/src/protocols/secure_channel/BUILD.gn
+++ b/src/protocols/secure_channel/BUILD.gn
@@ -61,4 +61,6 @@
     "${chip_root}/src/tracing:macros",
     "${chip_root}/src/transport",
   ]
+
+  deps = [ "${chip_root}/src/app:revision_info" ]
 }
diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp
index 2afc40f..5737564 100644
--- a/src/protocols/secure_channel/CASESession.cpp
+++ b/src/protocols/secure_channel/CASESession.cpp
@@ -41,6 +41,7 @@
 #include <protocols/Protocols.h>
 #include <protocols/secure_channel/CASEDestinationId.h>
 #include <protocols/secure_channel/PairingSession.h>
+#include <protocols/secure_channel/SessionParameters.h>
 #include <protocols/secure_channel/SessionResumptionStorage.h>
 #include <protocols/secure_channel/StatusReport.h>
 #include <system/SystemClock.h>
@@ -640,13 +641,11 @@
 CHIP_ERROR CASESession::SendSigma1()
 {
     MATTER_TRACE_SCOPE("SendSigma1", "CASESession");
-    const size_t mrpParamsSize =
-        mLocalMRPConfig.HasValue() ? TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t), sizeof(uint16_t)) : 0;
-    size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, // initiatorRandom
-                                                  sizeof(uint16_t),            // initiatorSessionId,
-                                                  kSHA256_Hash_Length,         // destinationId
-                                                  kP256_PublicKey_Length,      // InitiatorEphPubKey,
-                                                  mrpParamsSize,               // initiatorMRPParams
+    size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize,          // initiatorRandom
+                                                  sizeof(uint16_t),                     // initiatorSessionId,
+                                                  kSHA256_Hash_Length,                  // destinationId
+                                                  kP256_PublicKey_Length,               // InitiatorEphPubKey,
+                                                  SessionParameters::kEstimatedTLVSize, // initiatorSessionParams
                                                   SessionResumptionStorage::kResumptionIdSize, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES);
 
     System::PacketBufferTLVWriter tlvWriter;
@@ -699,11 +698,7 @@
     ReturnErrorOnFailure(
         tlvWriter.PutBytes(TLV::ContextTag(4), mEphemeralKey->Pubkey(), static_cast<uint32_t>(mEphemeralKey->Pubkey().Length())));
 
-    if (mLocalMRPConfig.HasValue())
-    {
-        ChipLogDetail(SecureChannel, "Including MRP parameters");
-        ReturnErrorOnFailure(EncodeMRPParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriter));
-    }
+    ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriter));
 
     // Try to find persistent session, and resume it.
     bool resuming = false;
@@ -916,10 +911,9 @@
 CHIP_ERROR CASESession::SendSigma2Resume()
 {
     MATTER_TRACE_SCOPE("SendSigma2Resume", "CASESession");
-    const size_t mrpParamsSize =
-        mLocalMRPConfig.HasValue() ? TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t), sizeof(uint16_t)) : 0;
-    size_t max_sigma2_resume_data_len = TLV::EstimateStructOverhead(
-        SessionResumptionStorage::kResumptionIdSize, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, sizeof(uint16_t), mrpParamsSize);
+    size_t max_sigma2_resume_data_len =
+        TLV::EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES,
+                                    sizeof(uint16_t), SessionParameters::kEstimatedTLVSize);
 
     System::PacketBufferTLVWriter tlvWriter;
     System::PacketBufferHandle msg_R2_resume;
@@ -948,11 +942,7 @@
 
     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), GetLocalSessionId().Value()));
 
-    if (mLocalMRPConfig.HasValue())
-    {
-        ChipLogDetail(SecureChannel, "Including MRP parameters");
-        ReturnErrorOnFailure(EncodeMRPParameters(TLV::ContextTag(4), mLocalMRPConfig.Value(), tlvWriter));
-    }
+    ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(4), mLocalMRPConfig, tlvWriter));
 
     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R2_resume));
@@ -1067,10 +1057,10 @@
                                          msg_R2_Encrypted.Get() + msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES));
 
     // Construct Sigma2 Msg
-    const size_t mrpParamsSize =
-        mLocalMRPConfig.HasValue() ? TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t), sizeof(uint16_t)) : 0;
-    size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, sizeof(uint16_t), kP256_PublicKey_Length,
-                                                  msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, mrpParamsSize);
+    size_t size_of_local_session_id = sizeof(uint16_t);
+    size_t data_len =
+        TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, size_of_local_session_id, kP256_PublicKey_Length,
+                                    msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, SessionParameters::kEstimatedTLVSize);
 
     System::PacketBufferHandle msg_R2 = System::PacketBufferHandle::New(data_len);
     VerifyOrReturnError(!msg_R2.IsNull(), CHIP_ERROR_NO_MEMORY);
@@ -1086,11 +1076,9 @@
                                                 static_cast<uint32_t>(mEphemeralKey->Pubkey().Length())));
     ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(4), msg_R2_Encrypted.Get(),
                                                 static_cast<uint32_t>(msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)));
-    if (mLocalMRPConfig.HasValue())
-    {
-        ChipLogDetail(SecureChannel, "Including MRP parameters");
-        ReturnErrorOnFailure(EncodeMRPParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriterMsg2));
-    }
+
+    ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriterMsg2));
+
     ReturnErrorOnFailure(tlvWriterMsg2.EndContainer(outerContainerType));
     ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msg_R2));
 
@@ -1147,7 +1135,7 @@
     if (tlvReader.Next() != CHIP_END_OF_TLV)
     {
         SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(4), tlvReader));
-        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
     }
 
     ChipLogDetail(SecureChannel, "Peer assigned session session ID %d", responderSessionId);
@@ -1340,7 +1328,7 @@
     if (tlvReader.Next() != CHIP_END_OF_TLV)
     {
         SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(kTag_Sigma2_ResponderMRPParams), tlvReader));
-        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
     }
 
 exit:
@@ -2029,7 +2017,7 @@
     if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kInitiatorMRPParamsTag))
     {
         ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(kInitiatorMRPParamsTag), tlvReader));
-        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
         err = tlvReader.Next();
     }
 
diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp
index 966bc1d..8e2f27f 100644
--- a/src/protocols/secure_channel/PASESession.cpp
+++ b/src/protocols/secure_channel/PASESession.cpp
@@ -41,6 +41,7 @@
 #include <lib/support/TypeTraits.h>
 #include <protocols/Protocols.h>
 #include <protocols/secure_channel/Constants.h>
+#include <protocols/secure_channel/SessionParameters.h>
 #include <protocols/secure_channel/StatusReport.h>
 #include <setup_payload/SetupPayload.h>
 #include <system/TLVPacketBufferBackingStore.h>
@@ -270,13 +271,12 @@
 
     ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
 
-    const size_t mrpParamsSize = mLocalMRPConfig.HasValue() ? TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t)) : 0;
-    const size_t max_msg_len   = TLV::EstimateStructOverhead(kPBKDFParamRandomNumberSize, // initiatorRandom,
-                                                             sizeof(uint16_t),            // initiatorSessionId
-                                                             sizeof(PasscodeId),          // passcodeId,
-                                                             sizeof(uint8_t),             // hasPBKDFParameters
-                                                             mrpParamsSize                // MRP Parameters
-      );
+    const size_t max_msg_len = TLV::EstimateStructOverhead(kPBKDFParamRandomNumberSize,         // initiatorRandom,
+                                                           sizeof(uint16_t),                    // initiatorSessionId
+                                                           sizeof(PasscodeId),                  // passcodeId,
+                                                           sizeof(uint8_t),                     // hasPBKDFParameters
+                                                           SessionParameters::kEstimatedTLVSize // Session Parameters
+    );
 
     System::PacketBufferHandle req = System::PacketBufferHandle::New(max_msg_len);
     VerifyOrReturnError(!req.IsNull(), CHIP_ERROR_NO_MEMORY);
@@ -290,11 +290,9 @@
     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), GetLocalSessionId().Value()));
     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), kDefaultCommissioningPasscodeId));
     ReturnErrorOnFailure(tlvWriter.PutBoolean(TLV::ContextTag(4), mHavePBKDFParameters));
-    if (mLocalMRPConfig.HasValue())
-    {
-        ChipLogDetail(SecureChannel, "Including MRP parameters in PBKDF param request");
-        ReturnErrorOnFailure(EncodeMRPParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriter));
-    }
+
+    ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriter));
+
     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     ReturnErrorOnFailure(tlvWriter.Finalize(&req));
 
@@ -357,7 +355,7 @@
     if (tlvReader.Next() != CHIP_END_OF_TLV)
     {
         SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
-        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+        mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
     }
 
     err = SendPBKDFParamResponse(ByteSpan(initiatorRandom), hasPBKDFParameters);
@@ -382,13 +380,12 @@
 
     ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
 
-    const size_t mrpParamsSize = mLocalMRPConfig.HasValue() ? TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t)) : 0;
     const size_t max_msg_len =
         TLV::EstimateStructOverhead(kPBKDFParamRandomNumberSize,                                // initiatorRandom
                                     kPBKDFParamRandomNumberSize,                                // responderRandom
                                     sizeof(uint16_t),                                           // responderSessionId
                                     TLV::EstimateStructOverhead(sizeof(uint32_t), mSaltLength), // pbkdf_parameters
-                                    mrpParamsSize                                               // MRP Parameters
+                                    SessionParameters::kEstimatedTLVSize                        // Session Parameters
         );
 
     System::PacketBufferHandle resp = System::PacketBufferHandle::New(max_msg_len);
@@ -413,11 +410,7 @@
         ReturnErrorOnFailure(tlvWriter.EndContainer(pbkdfParamContainer));
     }
 
-    if (mLocalMRPConfig.HasValue())
-    {
-        ChipLogDetail(SecureChannel, "Including MRP parameters in PBKDF param response");
-        ReturnErrorOnFailure(EncodeMRPParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriter));
-    }
+    ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriter));
 
     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     ReturnErrorOnFailure(tlvWriter.Finalize(&resp));
@@ -481,7 +474,7 @@
         if (tlvReader.Next() != CHIP_END_OF_TLV)
         {
             SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
-            mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+            mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
         }
 
         // TODO - Add a unit test that exercises mHavePBKDFParameters path
@@ -506,7 +499,7 @@
         if (tlvReader.Next() != CHIP_END_OF_TLV)
         {
             SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
-            mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(mRemoteMRPConfig);
+            mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteMRPConfig(GetRemoteMRPConfig());
         }
     }
 
diff --git a/src/protocols/secure_channel/PairingSession.cpp b/src/protocols/secure_channel/PairingSession.cpp
index af555bf..d3c6e96 100644
--- a/src/protocols/secure_channel/PairingSession.cpp
+++ b/src/protocols/secure_channel/PairingSession.cpp
@@ -18,6 +18,10 @@
 
 #include <protocols/secure_channel/PairingSession.h>
 
+#include <app/DataModelRevision.h>
+#include <app/InteractionModelRevision.h>
+#include <app/SpecificationVersion.h>
+#include <lib/core/CHIPConfig.h>
 #include <lib/core/TLVTypes.h>
 #include <lib/support/SafeInt.h>
 
@@ -44,7 +48,7 @@
 
     // Call Activate last, otherwise errors on anything after would lead to
     // a partially valid session.
-    secureSession->Activate(GetLocalScopedNodeId(), GetPeer(), GetPeerCATs(), peerSessionId, mRemoteMRPConfig);
+    secureSession->Activate(GetLocalScopedNodeId(), GetPeer(), GetPeerCATs(), peerSessionId, GetRemoteMRPConfig());
 
     ChipLogDetail(Inet, "New secure session activated for device " ChipLogFormatScopedNodeId ", LSID:%d PSID:%d!",
                   ChipLogValueScopedNodeId(GetPeer()), secureSession->GetLocalSessionId(), peerSessionId);
@@ -88,19 +92,44 @@
     }
 }
 
-CHIP_ERROR PairingSession::EncodeMRPParameters(TLV::Tag tag, const ReliableMessageProtocolConfig & mrpLocalConfig,
-                                               TLV::TLVWriter & tlvWriter)
+CHIP_ERROR PairingSession::EncodeSessionParameters(TLV::Tag tag, const Optional<ReliableMessageProtocolConfig> & providedMrpConfig,
+                                                   TLV::TLVWriter & tlvWriter)
 {
+    // TODO: https://github.com/project-chip/connectedhomeip/issues/30456. Based on the spec we need to send values here now,
+    // but it is not entirely clear what we should be sending here when `providedMrpConfig.HasValue() == false`. For now we
+    // are sending the default MRP config values.
+    ReliableMessageProtocolConfig mrpLocalConfig = GetDefaultMRPConfig();
+    if (providedMrpConfig.HasValue())
+    {
+        mrpLocalConfig = providedMrpConfig.Value();
+    }
     TLV::TLVType mrpParamsContainer;
     ReturnErrorOnFailure(tlvWriter.StartContainer(tag, TLV::kTLVType_Structure, mrpParamsContainer));
-    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), mrpLocalConfig.mIdleRetransTimeout.count()));
-    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), mrpLocalConfig.mActiveRetransTimeout.count()));
-    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), mrpLocalConfig.mActiveThresholdTime.count()));
+    ReturnErrorOnFailure(
+        tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSessionIdleInterval), mrpLocalConfig.mIdleRetransTimeout.count()));
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSessionActiveInterval),
+                                       mrpLocalConfig.mActiveRetransTimeout.count()));
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSessionActiveThreshold),
+                                       mrpLocalConfig.mActiveThresholdTime.count()));
+
+    uint16_t dataModel = CHIP_DEVICE_DATA_MODEL_REVISION;
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kDataModelRevision), dataModel));
+
+    uint16_t interactionModel = CHIP_DEVICE_INTERACTION_MODEL_REVISION;
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kInteractionModelRevision), interactionModel));
+
+    uint32_t specVersion = CHIP_DEVICE_SPECIFICATION_VERSION;
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSpecificationVersion), specVersion));
+
+    uint16_t maxPathsPerInvoke = CHIP_CONFIG_MAX_PATHS_PER_INVOKE;
+    ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kMaxPathsPerInvoke), maxPathsPerInvoke));
     return tlvWriter.EndContainer(mrpParamsContainer);
 }
 
 CHIP_ERROR PairingSession::DecodeMRPParametersIfPresent(TLV::Tag expectedTag, TLV::ContiguousBufferTLVReader & tlvReader)
 {
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
     // The MRP parameters are optional.
     if (tlvReader.GetTag() != expectedTag)
     {
@@ -110,50 +139,89 @@
     TLV::TLVType containerType = TLV::kTLVType_Structure;
     ReturnErrorOnFailure(tlvReader.EnterContainer(containerType));
 
-    uint32_t tlvElementValue = 0;
-
     ReturnErrorOnFailure(tlvReader.Next());
 
     ChipLogDetail(SecureChannel, "Found MRP parameters in the message");
 
     // All TLV elements in the structure are optional. If the first element is present, process it and move
     // the TLV reader to the next element.
-    if (TLV::TagNumFromTag(tlvReader.GetTag()) == 1)
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kSessionIdleInterval)
     {
-        ReturnErrorOnFailure(tlvReader.Get(tlvElementValue));
-        mRemoteMRPConfig.mIdleRetransTimeout = System::Clock::Milliseconds32(tlvElementValue);
+        uint32_t idleRetransTimeout;
+        ReturnErrorOnFailure(tlvReader.Get(idleRetransTimeout));
+        mRemoteSessionParams.SetMRPIdleRetransTimeout(System::Clock::Milliseconds32(idleRetransTimeout));
 
         // The next element is optional. If it's not present, return CHIP_NO_ERROR.
-        CHIP_ERROR err = tlvReader.Next();
-        if (err == CHIP_END_OF_TLV)
-        {
-            return tlvReader.ExitContainer(containerType);
-        }
-        ReturnErrorOnFailure(err);
+        SuccessOrExit(err = tlvReader.Next());
     }
 
-    if (TLV::TagNumFromTag(tlvReader.GetTag()) == 2)
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kSessionActiveInterval)
     {
-        ReturnErrorOnFailure(tlvReader.Get(tlvElementValue));
-        mRemoteMRPConfig.mActiveRetransTimeout = System::Clock::Milliseconds32(tlvElementValue);
+        uint32_t activeRetransTimeout;
+        ReturnErrorOnFailure(tlvReader.Get(activeRetransTimeout));
+        mRemoteSessionParams.SetMRPActiveRetransTimeout(System::Clock::Milliseconds32(activeRetransTimeout));
 
         // The next element is optional. If it's not present, return CHIP_NO_ERROR.
-        CHIP_ERROR err = tlvReader.Next();
-        if (err == CHIP_END_OF_TLV)
-        {
-            return tlvReader.ExitContainer(containerType);
-        }
-        ReturnErrorOnFailure(err);
+        SuccessOrExit(err = tlvReader.Next());
     }
 
-    if (TLV::TagNumFromTag(tlvReader.GetTag()) == 3)
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kSessionActiveThreshold)
     {
-        ReturnErrorOnFailure(tlvReader.Get(tlvElementValue));
-        mRemoteMRPConfig.mActiveThresholdTime = System::Clock::Milliseconds16(tlvElementValue);
+        uint16_t activeThresholdTime;
+        ReturnErrorOnFailure(tlvReader.Get(activeThresholdTime));
+        mRemoteSessionParams.SetMRPActiveThresholdTime(System::Clock::Milliseconds16(activeThresholdTime));
+
+        // The next element is optional. If it's not present, return CHIP_NO_ERROR.
+        SuccessOrExit(err = tlvReader.Next());
     }
+
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kDataModelRevision)
+    {
+        uint16_t dataModelRevision;
+        ReturnErrorOnFailure(tlvReader.Get(dataModelRevision));
+        mRemoteSessionParams.SetDataModelRevision(dataModelRevision);
+
+        // The next element is optional. If it's not present, return CHIP_NO_ERROR.
+        SuccessOrExit(err = tlvReader.Next());
+    }
+
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kInteractionModelRevision)
+    {
+        uint16_t interactionModelRevision;
+        ReturnErrorOnFailure(tlvReader.Get(interactionModelRevision));
+        mRemoteSessionParams.SetInteractionModelRevision(interactionModelRevision);
+
+        // The next element is optional. If it's not present, return CHIP_NO_ERROR.
+        SuccessOrExit(err = tlvReader.Next());
+    }
+
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kSpecificationVersion)
+    {
+        uint32_t specificationVersion;
+        ReturnErrorOnFailure(tlvReader.Get(specificationVersion));
+        mRemoteSessionParams.SetSpecificationVersion(specificationVersion);
+
+        // The next element is optional. If it's not present, return CHIP_NO_ERROR.
+        SuccessOrExit(err = tlvReader.Next());
+    }
+
+    if (TLV::TagNumFromTag(tlvReader.GetTag()) == SessionParameters::Tag::kMaxPathsPerInvoke)
+    {
+        uint16_t maxPathsPerInvoke;
+        ReturnErrorOnFailure(tlvReader.Get(maxPathsPerInvoke));
+        mRemoteSessionParams.SetMaxPathsPerInvoke(maxPathsPerInvoke);
+
+        // The next element is optional. If it's not present, return CHIP_NO_ERROR.
+        SuccessOrExit(err = tlvReader.Next());
+    }
+
     // Future proofing - Don't error out if there are other tags
-
-    return tlvReader.ExitContainer(containerType);
+exit:
+    if (err == CHIP_END_OF_TLV)
+    {
+        return tlvReader.ExitContainer(containerType);
+    }
+    return err;
 }
 
 bool PairingSession::IsSessionEstablishmentInProgress()
diff --git a/src/protocols/secure_channel/PairingSession.h b/src/protocols/secure_channel/PairingSession.h
index c604cd0..039705e 100644
--- a/src/protocols/secure_channel/PairingSession.h
+++ b/src/protocols/secure_channel/PairingSession.h
@@ -30,6 +30,7 @@
 #include <messaging/ExchangeContext.h>
 #include <protocols/secure_channel/Constants.h>
 #include <protocols/secure_channel/SessionEstablishmentDelegate.h>
+#include <protocols/secure_channel/SessionParameters.h>
 #include <protocols/secure_channel/StatusReport.h>
 #include <transport/CryptoContext.h>
 #include <transport/SecureSession.h>
@@ -96,14 +97,14 @@
      */
     virtual CHIP_ERROR DeriveSecureSession(CryptoContext & session) const = 0;
 
-    const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return mRemoteMRPConfig; }
-    void SetRemoteMRPConfig(const ReliableMessageProtocolConfig & config) { mRemoteMRPConfig = config; }
+    const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return mRemoteSessionParams.GetMRPConfig(); }
+    void SetRemoteMRPConfig(const ReliableMessageProtocolConfig & config) { mRemoteSessionParams.SetMRPConfig(config); }
 
     /**
-     * Encode the provided MRP parameters using the provided TLV tag.
+     * Encode the Session Parameters using the provided TLV tag.
      */
-    static CHIP_ERROR EncodeMRPParameters(TLV::Tag tag, const ReliableMessageProtocolConfig & mrpLocalConfig,
-                                          TLV::TLVWriter & tlvWriter);
+    static CHIP_ERROR EncodeSessionParameters(TLV::Tag tag, const Optional<ReliableMessageProtocolConfig> & mrpLocalConfig,
+                                              TLV::TLVWriter & tlvWriter);
 
 protected:
     /**
@@ -200,7 +201,7 @@
 
     /**
      * Try to decode the current element (pointed by the TLV reader) as MRP parameters.
-     * If the MRP parameters are found, mRemoteMRPConfig is updated with the devoded values.
+     * If the MRP parameters are found, mRemoteSessionParams is updated with the devoded values.
      *
      * MRP parameters are optional. So, if the TLV reader is not pointing to the MRP parameters,
      * the function is a noop.
@@ -231,9 +232,9 @@
     SessionEstablishmentDelegate * mDelegate   = nullptr;
 
     // mLocalMRPConfig is our config which is sent to the other end and used by the peer session.
-    // mRemoteMRPConfig is received from other end and set to our session.
+    // mRemoteSessionParams is received from other end and set to our session.
     Optional<ReliableMessageProtocolConfig> mLocalMRPConfig;
-    ReliableMessageProtocolConfig mRemoteMRPConfig = GetDefaultMRPConfig();
+    SessionParameters mRemoteSessionParams;
 
 private:
     Optional<uint16_t> mPeerSessionId;
diff --git a/src/protocols/secure_channel/SessionParameters.h b/src/protocols/secure_channel/SessionParameters.h
new file mode 100644
index 0000000..a595e78
--- /dev/null
+++ b/src/protocols/secure_channel/SessionParameters.h
@@ -0,0 +1,109 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <lib/core/TLV.h>
+#include <messaging/ReliableMessageProtocolConfig.h>
+
+namespace chip {
+
+// TODO We should get part of this from constexpr that is in ReliableMessageProtocolConfig.h
+
+class SessionParameters
+{
+public:
+    SessionParameters(ReliableMessageProtocolConfig mrpConfig = GetDefaultMRPConfig()) : mMRPConfig(mrpConfig) {}
+
+    // This estimated TLV size calc is here instead of messaging/ReliableMessageProtocolConfig.h
+    // because we would need to add `include <lib/core/TLV.h>`. While we could make it all work
+    // from a build standpoint, if any new MRP config gets added accessors will still need to be
+    // added here so having this calc done here isn't problematic.
+    static constexpr size_t kSizeOfSessionIdleInterval      = sizeof(uint32_t);
+    static constexpr size_t kSizeOfSessionActiveInterval    = sizeof(uint32_t);
+    static constexpr size_t kSizeOfSessionActiveThreshold   = sizeof(uint16_t);
+    static constexpr size_t kSizeOfDataModelRevision        = sizeof(uint16_t);
+    static constexpr size_t kSizeOfInteractionModelRevision = sizeof(uint16_t);
+    static constexpr size_t kSizeOfSpecificationVersion     = sizeof(uint32_t);
+    static constexpr size_t kSizeOfMaxPathsPerInvoke        = sizeof(uint16_t);
+
+    static constexpr size_t kEstimatedTLVSize = TLV::EstimateStructOverhead(
+        kSizeOfSessionIdleInterval, kSizeOfSessionActiveInterval, kSizeOfSessionActiveThreshold, kSizeOfDataModelRevision,
+        kSizeOfInteractionModelRevision, kSizeOfSpecificationVersion, kSizeOfMaxPathsPerInvoke);
+
+    // From Section 4.12.8 "Parameters and Constants" in chapter "Secure Channel".
+    enum Tag : uint32_t
+    {
+        kSessionIdleInterval      = 1,
+        kSessionActiveInterval    = 2,
+        kSessionActiveThreshold   = 3,
+        kDataModelRevision        = 4,
+        kInteractionModelRevision = 5,
+        kSpecificationVersion     = 6,
+        kMaxPathsPerInvoke        = 7,
+    };
+
+    const ReliableMessageProtocolConfig & GetMRPConfig() const { return mMRPConfig; }
+    void SetMRPConfig(const ReliableMessageProtocolConfig & config) { mMRPConfig = config; }
+    void SetMRPIdleRetransTimeout(const System::Clock::Milliseconds32 idleRetransTimeout)
+    {
+        mMRPConfig.mIdleRetransTimeout = idleRetransTimeout;
+    }
+    void SetMRPActiveRetransTimeout(const System::Clock::Milliseconds32 activeRetransTimeout)
+    {
+        mMRPConfig.mActiveRetransTimeout = activeRetransTimeout;
+    }
+    void SetMRPActiveThresholdTime(const System::Clock::Milliseconds16 activeThresholdTime)
+    {
+        mMRPConfig.mActiveThresholdTime = activeThresholdTime;
+    }
+
+    const Optional<uint16_t> & GetDataModelRevision() const { return mDataModelRevision; }
+    void SetDataModelRevision(const uint16_t dataModelRevision) { mDataModelRevision = MakeOptional(dataModelRevision); }
+
+    const Optional<uint16_t> & GetInteractionModelRevision() const { return mInteractionModelRevision; }
+    void SetInteractionModelRevision(const uint16_t interactionModelRevision)
+    {
+        mInteractionModelRevision = MakeOptional(interactionModelRevision);
+    }
+
+    const Optional<uint32_t> & GetSpecificationVersion() const { return mSpecificationVersion; }
+    void SetSpecificationVersion(const uint32_t specificationVersion)
+    {
+        mSpecificationVersion = MakeOptional(specificationVersion);
+    }
+
+    uint16_t GetMaxPathsPerInvoke() const { return mMaxPathsPerInvoke; }
+    void SetMaxPathsPerInvoke(const uint16_t maxPathsPerInvoke) { mMaxPathsPerInvoke = maxPathsPerInvoke; }
+
+private:
+    ReliableMessageProtocolConfig mMRPConfig;
+    // For legacy reasons if we do not get DataModelRevision it means either 16 or 17. But there isn't
+    // a way to know for certain.
+    Optional<uint16_t> mDataModelRevision;
+    // For legacy reasons if we do not get InteractionModelRevision it means either 10 or 11. But there
+    // isn't a way to know for certain.
+    Optional<uint16_t> mInteractionModelRevision;
+    // For legacy reasons if we do not get SpecificationVersion it means that version is less than
+    // 0x01030000. But there isn't a way to know for certain.
+    Optional<uint32_t> mSpecificationVersion;
+    // When maxPathsPerInvoke is not provided legacy is always 1
+    uint16_t mMaxPathsPerInvoke = 1;
+};
+
+} // namespace chip
diff --git a/src/protocols/secure_channel/tests/TestPairingSession.cpp b/src/protocols/secure_channel/tests/TestPairingSession.cpp
index 714a18e..ac1c453 100644
--- a/src/protocols/secure_channel/tests/TestPairingSession.cpp
+++ b/src/protocols/secure_channel/tests/TestPairingSession.cpp
@@ -46,7 +46,7 @@
 
     void OnSessionReleased() override {}
 
-    const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return mRemoteMRPConfig; }
+    const ReliableMessageProtocolConfig & GetRemoteMRPConfig() const { return PairingSession::GetRemoteMRPConfig(); }
 
     CHIP_ERROR DeriveSecureSession(CryptoContext & session) const override { return CHIP_NO_ERROR; }
 
@@ -70,7 +70,8 @@
     NL_TEST_ASSERT(inSuite,
                    writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType) == CHIP_NO_ERROR);
 
-    NL_TEST_ASSERT(inSuite, PairingSession::EncodeMRPParameters(TLV::ContextTag(1), config, writer) == CHIP_NO_ERROR);
+    NL_TEST_ASSERT(inSuite,
+                   PairingSession::EncodeSessionParameters(TLV::ContextTag(1), MakeOptional(config), writer) == CHIP_NO_ERROR);
 
     NL_TEST_ASSERT(inSuite, writer.EndContainer(outerContainerType) == CHIP_NO_ERROR);
     NL_TEST_ASSERT(inSuite, writer.Finalize(&buf) == CHIP_NO_ERROR);