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);