From 13a8f487b8143b254bc3b9271bddde2f8f420d6a Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 29 Nov 2024 17:54:31 +0100 Subject: [PATCH 01/16] Removing networking bits from CASESession ParseSigma1 and creating EncodeSigma1 --- src/protocols/secure_channel/CASESession.cpp | 198 ++++++++++-------- src/protocols/secure_channel/CASESession.h | 22 +- .../secure_channel/tests/TestCASESession.cpp | 23 +- 3 files changed, 136 insertions(+), 107 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 007a58659f45cd..269f4249420b87 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -68,16 +67,13 @@ enum kTag_TBSData_ReceiverPubKey = 4, }; -enum -{ - kTag_Sigma1_InitiatorRandom = 1, - kTag_Sigma1_InitiatorSessionId = 2, - kTag_Sigma1_DestinationId = 3, - kTag_Sigma1_InitiatorEphPubKey = 4, - kTag_Sigma1_InitiatorMRPParams = 5, - kTag_Sigma1_ResumptionID = 6, - kTag_Sigma1_InitiatorResumeMIC = 7, -}; +inline constexpr uint8_t kInitiatorRandomTag = 1; +inline constexpr uint8_t kInitiatorSessionIdTag = 2; +inline constexpr uint8_t kDestinationIdTag = 3; +inline constexpr uint8_t kInitiatorPubKeyTag = 4; +inline constexpr uint8_t kInitiatorMRPParamsTag = 5; +inline constexpr uint8_t kResumptionIDTag = 6; +inline constexpr uint8_t kResume1MICTag = 7; enum { @@ -770,24 +766,19 @@ void CASESession::HandleConnectionClosed(Transport::ActiveTCPConnectionState * c CHIP_ERROR CASESession::SendSigma1() { MATTER_TRACE_SCOPE("SendSigma1", "CASESession"); - 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; System::PacketBufferHandle msg_R1; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; + Sigma1Param encodeSigma1Params; + // Lookup fabric info. const auto * fabricInfo = mFabricsTable->FindFabricWithIndex(mFabricIndex); VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INCORRECT_STATE); // Validate that we have a session ID allocated. VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); + encodeSigma1Params.initiatorSessionId = GetLocalSessionId().Value(); // Generate an ephemeral keypair mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); @@ -797,16 +788,6 @@ CHIP_ERROR CASESession::SendSigma1() // Fill in the random value ReturnErrorOnFailure(DRBG_get_bytes(mInitiatorRandom, sizeof(mInitiatorRandom))); - // Construct Sigma1 Msg - msg_R1 = System::PacketBufferHandle::New(data_len); - VerifyOrReturnError(!msg_R1.IsNull(), CHIP_ERROR_NO_MEMORY); - - tlvWriter.Init(std::move(msg_R1)); - ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), ByteSpan(mInitiatorRandom))); - // Retrieve Session Identifier - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), GetLocalSessionId().Value())); - // Generate a Destination Identifier based on the node we are attempting to reach { // Obtain originator IPK matching the fabric where we are trying to open a session. mIPK @@ -821,14 +802,10 @@ CHIP_ERROR CASESession::SendSigma1() MutableByteSpan destinationIdSpan(destinationIdentifier); ReturnErrorOnFailure(GenerateCaseDestinationId(ByteSpan(mIPK), ByteSpan(mInitiatorRandom), rootPubKeySpan, fabricId, mPeerNodeId, destinationIdSpan)); + encodeSigma1Params.destinationId = destinationIdSpan; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(3), destinationIdentifier, sizeof(destinationIdentifier))); - - ReturnErrorOnFailure( - tlvWriter.PutBytes(TLV::ContextTag(4), mEphemeralKey->Pubkey(), static_cast(mEphemeralKey->Pubkey().Length()))); VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriter)); // Try to find persistent session, and resume it. bool resuming = false; @@ -839,20 +816,20 @@ CHIP_ERROR CASESession::SendSigma1() if (err == CHIP_NO_ERROR) { // Found valid resumption state, try to resume the session. - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(6), mResumeResumptionId)); - uint8_t initiatorResume1MIC[CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - MutableByteSpan resumeMICSpan(initiatorResume1MIC); + MutableByteSpan resumeMICSpan(encodeSigma1Params.initiatorResume1MIC); ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), ByteSpan(mResumeResumptionId), ByteSpan(kKDFS1RKeyInfo), ByteSpan(kResume1MIC_Nonce), resumeMICSpan)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(7), resumeMICSpan)); + encodeSigma1Params.initiatorResumeMICSpan = resumeMICSpan; + encodeSigma1Params.sessionResumptionRequested = true; + resuming = true; } } - ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R1)); + // Encode Sigma1 into into msg_R1 + ReturnErrorOnFailure(EncodeSigma1(msg_R1, encodeSigma1Params)); ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R1->Start(), msg_R1->DataLength() })); @@ -884,6 +861,52 @@ CHIP_ERROR CASESession::SendSigma1() return CHIP_NO_ERROR; } +CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, Sigma1Param & inputParams) +{ + + MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); + + 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); + + msg = System::PacketBufferHandle::New(data_len); + VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); + + System::PacketBufferTLVWriter tlvWriter; + TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + + tlvWriter.Init(std::move(msg)); + ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); + // TODO Pass this in the struct? + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorRandomTag), ByteSpan(mInitiatorRandom))); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorSessionIdTag), inputParams.initiatorSessionId)); + + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kDestinationIdTag), inputParams.destinationId)); + + // TODO Pass this in the struct? + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kInitiatorPubKeyTag), mEphemeralKey->Pubkey(), + static_cast(mEphemeralKey->Pubkey().Length()))); + + // TODO is it redudunt? + VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(kInitiatorMRPParamsTag), mLocalMRPConfig.Value(), tlvWriter)); + + if (inputParams.sessionResumptionRequested) + { + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResumptionIDTag), mResumeResumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResume1MICTag), inputParams.initiatorResumeMICSpan)); + } + + ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); + ReturnErrorOnFailure(tlvWriter.Finalize(&msg)); + + return CHIP_NO_ERROR; +} + CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle && msg) { MATTER_TRACE_SCOPE("HandleSigma1_and_SendSigma2", "CASESession"); @@ -923,7 +946,7 @@ CHIP_ERROR CASESession::FindLocalNodeFromDestinationId(const ByteSpan & destinat MutableByteSpan candidateDestinationIdSpan(candidateDestinationId); ByteSpan candidateIpkSpan(ipkKeySet.epoch_keys[keyIdx].key); - err = GenerateCaseDestinationId(ByteSpan(candidateIpkSpan), ByteSpan(initiatorRandom), rootPubKeySpan, fabricId, nodeId, + err = GenerateCaseDestinationId(candidateIpkSpan, initiatorRandom, rootPubKeySpan, fabricId, nodeId, candidateDestinationIdSpan); if ((err == CHIP_NO_ERROR) && (candidateDestinationIdSpan.data_equal(destinationId))) { @@ -974,38 +997,43 @@ CHIP_ERROR CASESession::TryResumeSession(SessionResumptionStorage::ConstResumpti CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) { MATTER_TRACE_SCOPE("HandleSigma1", "CASESession"); - CHIP_ERROR err = CHIP_NO_ERROR; - System::PacketBufferTLVReader tlvReader; - - uint16_t initiatorSessionId; - ByteSpan destinationIdentifier; - ByteSpan initiatorRandom; - ChipLogProgress(SecureChannel, "Received Sigma1 msg"); MATTER_TRACE_COUNTER("Sigma1"); - bool sessionResumptionRequested = false; - ByteSpan resumptionId; - ByteSpan resume1MIC; - ByteSpan initiatorPubKey; + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferTLVReader tlvReader; + + Sigma1Param parsedSigma1; SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); tlvReader.Init(std::move(msg)); - SuccessOrExit(err = ParseSigma1(tlvReader, initiatorRandom, initiatorSessionId, destinationIdentifier, initiatorPubKey, - sessionResumptionRequested, resumptionId, resume1MIC)); - ChipLogDetail(SecureChannel, "Peer assigned session key ID %d", initiatorSessionId); - SetPeerSessionId(initiatorSessionId); + SuccessOrExit(err = ParseSigma1(tlvReader, parsedSigma1)); + + ChipLogDetail(SecureChannel, "Peer assigned session key ID %d", parsedSigma1.initiatorSessionId); + SetPeerSessionId(parsedSigma1.initiatorSessionId); VerifyOrExit(mFabricsTable != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - if (sessionResumptionRequested && resumptionId.size() == SessionResumptionStorage::kResumptionIdSize && + // TODO: Added by Amine, taken from inside ParseSigma1 + // This was removed to remove the non-parsing parts from ParseSigma1, decoupling it from higher levels + // TODO: Should i change it? + // Set the recieved MRP parameters included with Sigma1 + if (parsedSigma1.InitiatorMRPParamsPresent == true) + { + mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( + GetRemoteSessionParameters()); + } + + if (parsedSigma1.sessionResumptionRequested && + parsedSigma1.resumptionId.size() == SessionResumptionStorage::kResumptionIdSize && CHIP_NO_ERROR == - TryResumeSession(SessionResumptionStorage::ConstResumptionIdView(resumptionId.data()), resume1MIC, initiatorRandom)) + TryResumeSession(SessionResumptionStorage::ConstResumptionIdView(parsedSigma1.resumptionId.data()), + parsedSigma1.initiatorResumeMICSpan, parsedSigma1.initiatorRandom)) { - std::copy(initiatorRandom.begin(), initiatorRandom.end(), mInitiatorRandom); - std::copy(resumptionId.begin(), resumptionId.end(), mResumeResumptionId.begin()); + std::copy(parsedSigma1.initiatorRandom.begin(), parsedSigma1.initiatorRandom.end(), mInitiatorRandom); + std::copy(parsedSigma1.resumptionId.begin(), parsedSigma1.resumptionId.end(), mResumeResumptionId.begin()); // Send Sigma2Resume message to the initiator MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); @@ -1023,7 +1051,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) } // Attempt to match the initiator's desired destination based on local fabric table. - err = FindLocalNodeFromDestinationId(destinationIdentifier, initiatorRandom); + err = FindLocalNodeFromDestinationId(parsedSigma1.destinationId, parsedSigma1.initiatorRandom); if (err == CHIP_NO_ERROR) { ChipLogProgress(SecureChannel, "CASE matched destination ID: fabricIndex %u, NodeID 0x" ChipLogFormatX64, @@ -1035,13 +1063,13 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) else { ChipLogError(SecureChannel, "CASE failed to match destination ID with local fabrics"); - ChipLogByteSpan(SecureChannel, destinationIdentifier); + ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); } SuccessOrExit(err); // ParseSigma1 ensures that: // mRemotePubKey.Length() == initiatorPubKey.size() == kP256_PublicKey_Length. - memcpy(mRemotePubKey.Bytes(), initiatorPubKey.data(), mRemotePubKey.Length()); + memcpy(mRemotePubKey.Bytes(), parsedSigma1.initiatorEphPubKey.data(), mRemotePubKey.Length()); MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); err = SendSigma2(); @@ -2163,46 +2191,36 @@ CHIP_ERROR CASESession::OnFailureStatusReport(Protocols::SecureChannel::GeneralS return err; } -CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ByteSpan & initiatorRandom, - uint16_t & initiatorSessionId, ByteSpan & destinationId, ByteSpan & initiatorEphPubKey, - bool & resumptionRequested, ByteSpan & resumptionId, ByteSpan & initiatorResumeMIC) +CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, Sigma1Param & output) { using namespace TLV; - constexpr uint8_t kInitiatorRandomTag = 1; - constexpr uint8_t kInitiatorSessionIdTag = 2; - constexpr uint8_t kDestinationIdTag = 3; - constexpr uint8_t kInitiatorPubKeyTag = 4; - constexpr uint8_t kInitiatorMRPParamsTag = 5; - constexpr uint8_t kResumptionIDTag = 6; - constexpr uint8_t kResume1MICTag = 7; - TLVType containerType = kTLVType_Structure; ReturnErrorOnFailure(tlvReader.Next(containerType, AnonymousTag())); ReturnErrorOnFailure(tlvReader.EnterContainer(containerType)); ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorRandomTag))); - ReturnErrorOnFailure(tlvReader.GetByteView(initiatorRandom)); - VerifyOrReturnError(initiatorRandom.size() == kSigmaParamRandomNumberSize, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorRandom)); + VerifyOrReturnError(output.initiatorRandom.size() == kSigmaParamRandomNumberSize, CHIP_ERROR_INVALID_CASE_PARAMETER); ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorSessionIdTag))); - ReturnErrorOnFailure(tlvReader.Get(initiatorSessionId)); + ReturnErrorOnFailure(tlvReader.Get(output.initiatorSessionId)); ReturnErrorOnFailure(tlvReader.Next(ContextTag(kDestinationIdTag))); - ReturnErrorOnFailure(tlvReader.GetByteView(destinationId)); - VerifyOrReturnError(destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.GetByteView(output.destinationId)); + VerifyOrReturnError(output.destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorPubKeyTag))); - ReturnErrorOnFailure(tlvReader.GetByteView(initiatorEphPubKey)); - VerifyOrReturnError(initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorEphPubKey)); + VerifyOrReturnError(output.initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); // Optional members start here. CHIP_ERROR err = tlvReader.Next(); if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kInitiatorMRPParamsTag)) { ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(kInitiatorMRPParamsTag), tlvReader)); - mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( - GetRemoteSessionParameters()); + output.InitiatorMRPParamsPresent = true; + err = tlvReader.Next(); } @@ -2212,16 +2230,18 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kResumptionIDTag)) { resumptionIDTagFound = true; - ReturnErrorOnFailure(tlvReader.GetByteView(resumptionId)); - VerifyOrReturnError(resumptionId.size() == SessionResumptionStorage::kResumptionIdSize, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.GetByteView(output.resumptionId)); + VerifyOrReturnError(output.resumptionId.size() == SessionResumptionStorage::kResumptionIdSize, + CHIP_ERROR_INVALID_CASE_PARAMETER); err = tlvReader.Next(); } if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kResume1MICTag)) { resume1MICTagFound = true; - ReturnErrorOnFailure(tlvReader.GetByteView(initiatorResumeMIC)); - VerifyOrReturnError(initiatorResumeMIC.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorResumeMICSpan)); + VerifyOrReturnError(output.initiatorResumeMICSpan.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, + CHIP_ERROR_INVALID_CASE_PARAMETER); err = tlvReader.Next(); } @@ -2236,11 +2256,11 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, if (resumptionIDTagFound && resume1MICTagFound) { - resumptionRequested = true; + output.sessionResumptionRequested = true; } else if (!resumptionIDTagFound && !resume1MICTagFound) { - resumptionRequested = false; + output.sessionResumptionRequested = false; } else { diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 045d1982dd723c..65c480e1052fbc 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,19 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, */ void SetGroupDataProvider(Credentials::GroupDataProvider * groupDataProvider) { mGroupDataProvider = groupDataProvider; } + struct Sigma1Param + { + ByteSpan initiatorRandom; + uint16_t initiatorSessionId; + ByteSpan destinationId; + ByteSpan initiatorEphPubKey; + bool sessionResumptionRequested = false; + bool InitiatorMRPParamsPresent = false; + ByteSpan resumptionId; + ByteSpan initiatorResumeMICSpan; + uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + }; + /** * Parse a sigma1 message. This function will return success only if the * message passes schema checks. Specifically: @@ -135,9 +149,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * and the resumptionID and initiatorResumeMIC outparams will be set to * valid values, or the resumptionRequested outparam will be set to false. */ - CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ByteSpan & initiatorRandom, uint16_t & initiatorSessionId, - ByteSpan & destinationId, ByteSpan & initiatorEphPubKey, bool & resumptionRequested, - ByteSpan & resumptionId, ByteSpan & initiatorResumeMIC); + CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, Sigma1Param & OutputParseSigma1); + + // TODO: Add message + // TODO: should i keep it as public? why is ParseSigma1 public? + CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & msg, Sigma1Param & encodeSigma1); /** * @brief diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 67b4cdd7d69faf..51cc2fe9a35199 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -708,7 +708,7 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) // I wish we had "if constexpr" support here, so the compiler would know // resumptionIdLen is nonzero inside the block.... - if (Params::resumptionIdLen != 0) + if constexpr (Params::resumptionIdLen != 0) { uint8_t resumptionId[Params::resumptionIdLen]; @@ -718,7 +718,7 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) writer.Put(Params::NumToTag(Params::resumptionIdTag), ByteSpan(resumptionId, Params::resumptionIdLen))); } - if (Params::initiatorResumeMICLen != 0) + if constexpr (Params::initiatorResumeMICLen != 0) { uint8_t initiatorResumeMIC[Params::initiatorResumeMICLen]; // to fix _FORTIFY_SOURCE issue, _FORTIFY_SOURCE=2 by default on Android @@ -727,7 +727,7 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) ByteSpan(initiatorResumeMIC, Params::initiatorResumeMICLen))); } - if (Params::includeStructEnd) + if constexpr (Params::includeStructEnd) { ReturnErrorOnFailure(writer.EndContainer(containerType)); } @@ -745,21 +745,14 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - \ - ByteSpan initiatorRandom; \ - uint16_t initiatorSessionId; \ - ByteSpan destinationId; \ - ByteSpan initiatorEphPubKey; \ - bool resumptionRequested; \ - ByteSpan resumptionId; \ - ByteSpan initiatorResumeMIC; \ + CASESession::Sigma1Param parsedSigma1; \ CASESession session; \ - EXPECT_EQ(session.ParseSigma1(reader, initiatorRandom, initiatorSessionId, destinationId, initiatorEphPubKey, \ - resumptionRequested, resumptionId, initiatorResumeMIC) == CHIP_NO_ERROR, \ - params::expectSuccess); \ + \ + EXPECT_EQ(session.ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ if (params::expectSuccess) \ { \ - EXPECT_EQ(resumptionRequested, params::resumptionIdLen != 0 && params::initiatorResumeMICLen != 0); \ + EXPECT_EQ(parsedSigma1.sessionResumptionRequested, \ + params::resumptionIdLen != 0 && params::initiatorResumeMICLen != 0); \ /* Add other verification tests here as desired */ \ } \ } while (0) From 224a6261557182c2e5909cd40c2dbdfbc04c8927 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Mon, 2 Dec 2024 19:43:38 +0100 Subject: [PATCH 02/16] integrating comments --- src/protocols/secure_channel/CASESession.cpp | 67 +++++++++---------- src/protocols/secure_channel/CASESession.h | 32 +++++++-- .../secure_channel/tests/TestCASESession.cpp | 2 +- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 269f4249420b87..0a4fd6f6ee086c 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -770,7 +770,7 @@ CHIP_ERROR CASESession::SendSigma1() System::PacketBufferHandle msg_R1; uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; - Sigma1Param encodeSigma1Params; + EncodeSigma1Param encodeSigma1Params; // Lookup fabric info. const auto * fabricInfo = mFabricsTable->FindFabricWithIndex(mFabricIndex); @@ -784,9 +784,11 @@ CHIP_ERROR CASESession::SendSigma1() mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); + encodeSigma1Params.pEphPubKey = &mEphemeralKey->Pubkey(); // Fill in the random value ReturnErrorOnFailure(DRBG_get_bytes(mInitiatorRandom, sizeof(mInitiatorRandom))); + encodeSigma1Params.initiatorRandom = ByteSpan(mInitiatorRandom); // Generate a Destination Identifier based on the node we are attempting to reach { @@ -800,15 +802,15 @@ CHIP_ERROR CASESession::SendSigma1() Credentials::P256PublicKeySpan rootPubKeySpan{ rootPubKey.ConstBytes() }; MutableByteSpan destinationIdSpan(destinationIdentifier); - ReturnErrorOnFailure(GenerateCaseDestinationId(ByteSpan(mIPK), ByteSpan(mInitiatorRandom), rootPubKeySpan, fabricId, + ReturnErrorOnFailure(GenerateCaseDestinationId(ByteSpan(mIPK), encodeSigma1Params.initiatorRandom, rootPubKeySpan, fabricId, mPeerNodeId, destinationIdSpan)); encodeSigma1Params.destinationId = destinationIdSpan; } VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + encodeSigma1Params.initiatorMrpConfig = &mLocalMRPConfig.Value(); // Try to find persistent session, and resume it. - bool resuming = false; if (mSessionResumptionStorage != nullptr) { CHIP_ERROR err = mSessionResumptionStorage->FindByScopedNodeId(fabricInfo->GetScopedNodeIdForNode(mPeerNodeId), @@ -817,14 +819,13 @@ CHIP_ERROR CASESession::SendSigma1() { // Found valid resumption state, try to resume the session. + encodeSigma1Params.resumptionId = mResumeResumptionId; MutableByteSpan resumeMICSpan(encodeSigma1Params.initiatorResume1MIC); - ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), ByteSpan(mResumeResumptionId), + ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Params.initiatorRandom, encodeSigma1Params.resumptionId, ByteSpan(kKDFS1RKeyInfo), ByteSpan(kResume1MIC_Nonce), resumeMICSpan)); encodeSigma1Params.initiatorResumeMICSpan = resumeMICSpan; encodeSigma1Params.sessionResumptionRequested = true; - - resuming = true; } } @@ -837,7 +838,7 @@ CHIP_ERROR CASESession::SendSigma1() ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma1, std::move(msg_R1), SendFlags(SendMessageFlags::kExpectResponse))); - if (resuming) + if (encodeSigma1Params.sessionResumptionRequested) { mState = State::kSentSigma1Resume; @@ -861,17 +862,19 @@ CHIP_ERROR CASESession::SendSigma1() return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, Sigma1Param & inputParams) +CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Param & input) { MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); - 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); + 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, // resumptionId + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES // initiatorResumeMIC + ); msg = System::PacketBufferHandle::New(data_len); VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); @@ -881,24 +884,21 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, Sigma1Par tlvWriter.Init(std::move(msg)); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - // TODO Pass this in the struct? - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorRandomTag), ByteSpan(mInitiatorRandom))); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorSessionIdTag), inputParams.initiatorSessionId)); - - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kDestinationIdTag), inputParams.destinationId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorRandomTag), input.initiatorRandom)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorSessionIdTag), input.initiatorSessionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kDestinationIdTag), input.destinationId)); - // TODO Pass this in the struct? - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kInitiatorPubKeyTag), mEphemeralKey->Pubkey(), - static_cast(mEphemeralKey->Pubkey().Length()))); + VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kInitiatorPubKeyTag), *input.pEphPubKey, + static_cast(input.pEphPubKey->Length()))); - // TODO is it redudunt? - VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(kInitiatorMRPParamsTag), mLocalMRPConfig.Value(), tlvWriter)); + VerifyOrReturnError(input.initiatorMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(kInitiatorMRPParamsTag), *input.initiatorMrpConfig, tlvWriter)); - if (inputParams.sessionResumptionRequested) + if (input.sessionResumptionRequested) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResumptionIDTag), mResumeResumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResume1MICTag), inputParams.initiatorResumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResumptionIDTag), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResume1MICTag), input.initiatorResumeMICSpan)); } ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); @@ -1003,7 +1003,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) CHIP_ERROR err = CHIP_NO_ERROR; System::PacketBufferTLVReader tlvReader; - Sigma1Param parsedSigma1; + ParseSigma1Param parsedSigma1; SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); @@ -1016,11 +1016,8 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) VerifyOrExit(mFabricsTable != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - // TODO: Added by Amine, taken from inside ParseSigma1 - // This was removed to remove the non-parsing parts from ParseSigma1, decoupling it from higher levels - // TODO: Should i change it? - // Set the recieved MRP parameters included with Sigma1 - if (parsedSigma1.InitiatorMRPParamsPresent == true) + // Set the MRP parameters provided in the Sigma1 message + if (parsedSigma1.InitiatorMRPParamsPresent) { mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( GetRemoteSessionParameters()); @@ -2191,7 +2188,7 @@ CHIP_ERROR CASESession::OnFailureStatusReport(Protocols::SecureChannel::GeneralS return err; } -CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, Sigma1Param & output) +CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & output) { using namespace TLV; diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 65c480e1052fbc..4464423da151ce 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -51,6 +51,10 @@ namespace chip { +namespace Testing { +class FuzzCASESession; +} + // TODO: temporary derive from Messaging::UnsolicitedMessageHandler, actually the CASEServer should be the umh, it will be fixed // when implementing concurrent CASE session. class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, @@ -118,19 +122,35 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, */ void SetGroupDataProvider(Credentials::GroupDataProvider * groupDataProvider) { mGroupDataProvider = groupDataProvider; } + // This struct is only serves as a base struct for EncodeSigma1 and ParseSigma1 struct Sigma1Param { ByteSpan initiatorRandom; uint16_t initiatorSessionId; ByteSpan destinationId; - ByteSpan initiatorEphPubKey; bool sessionResumptionRequested = false; - bool InitiatorMRPParamsPresent = false; ByteSpan resumptionId; ByteSpan initiatorResumeMICSpan; + }; + + struct EncodeSigma1Param : Sigma1Param + { + const Crypto::P256PublicKey * pEphPubKey; + const ReliableMessageProtocolConfig * initiatorMrpConfig; uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; }; + struct ParseSigma1Param : Sigma1Param + { + ByteSpan initiatorEphPubKey; + bool InitiatorMRPParamsPresent = false; + }; + + /* + * TLV Encodes a Sigma1 message into the payload handled by msg + */ + CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Param & InputEncodeSigma1); + /** * Parse a sigma1 message. This function will return success only if the * message passes schema checks. Specifically: @@ -149,11 +169,8 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * and the resumptionID and initiatorResumeMIC outparams will be set to * valid values, or the resumptionRequested outparam will be set to false. */ - CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, Sigma1Param & OutputParseSigma1); - - // TODO: Add message - // TODO: should i keep it as public? why is ParseSigma1 public? - CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & msg, Sigma1Param & encodeSigma1); + CHIP_ERROR + ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & OutputParseSigma1); /** * @brief @@ -229,6 +246,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, private: friend class TestCASESession; + friend class Testing::FuzzCASESession; using AutoReleaseSessionKey = Crypto::AutoReleaseSymmetricKey; diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 51cc2fe9a35199..ccc4f142a03c51 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -745,7 +745,7 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - CASESession::Sigma1Param parsedSigma1; \ + CASESession::ParseSigma1Param parsedSigma1; \ CASESession session; \ \ EXPECT_EQ(session.ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ From b3978ba43fb4ff656e6c293915e5093ac64851c6 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Mon, 9 Dec 2024 18:43:35 +0100 Subject: [PATCH 03/16] Refactoring HandleSigma1_and_SendSigma2 and functions called within it --- src/protocols/secure_channel/CASESession.cpp | 301 ++++++++++++------ src/protocols/secure_channel/CASESession.h | 89 +++++- .../secure_channel/tests/TestCASESession.cpp | 172 ++++++++++ 3 files changed, 450 insertions(+), 112 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 0a4fd6f6ee086c..be7f667311def7 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -67,6 +67,7 @@ enum kTag_TBSData_ReceiverPubKey = 4, }; +// Sigma1 TLV Tags inline constexpr uint8_t kInitiatorRandomTag = 1; inline constexpr uint8_t kInitiatorSessionIdTag = 2; inline constexpr uint8_t kDestinationIdTag = 3; @@ -75,6 +76,8 @@ inline constexpr uint8_t kInitiatorMRPParamsTag = 5; inline constexpr uint8_t kResumptionIDTag = 6; inline constexpr uint8_t kResume1MICTag = 7; +// Sigma2 TLV Tags +// TODO: either use constexpr, or enum for all enum { kTag_Sigma2_ResponderRandom = 1, @@ -84,6 +87,15 @@ enum kTag_Sigma2_ResponderMRPParams = 5, }; +// Sigma2Resume TLV Tags +enum +{ + kTag_Sigma2Res_ResumptionID = 1, + kTag_Sigma2Res_Sigma2ResumeMIC = 2, + kTag_Sigma2Res_ResponderSessionID = 3, + kTag_Sigma2Res_ResponderMRPParams = 4, +}; + enum { kTag_Sigma3_Encrypted3 = 1, @@ -770,6 +782,7 @@ CHIP_ERROR CASESession::SendSigma1() System::PacketBufferHandle msg_R1; uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; + // Struct that will be used as input to EncodeSigma1() method EncodeSigma1Param encodeSigma1Params; // Lookup fabric info. @@ -818,7 +831,6 @@ CHIP_ERROR CASESession::SendSigma1() if (err == CHIP_NO_ERROR) { // Found valid resumption state, try to resume the session. - encodeSigma1Params.resumptionId = mResumeResumptionId; MutableByteSpan resumeMICSpan(encodeSigma1Params.initiatorResume1MIC); ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Params.initiatorRandom, encodeSigma1Params.resumptionId, @@ -829,7 +841,7 @@ CHIP_ERROR CASESession::SendSigma1() } } - // Encode Sigma1 into into msg_R1 + // Encode Sigma1 in CHIP TLV Format ReturnErrorOnFailure(EncodeSigma1(msg_R1, encodeSigma1Params)); ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R1->Start(), msg_R1->DataLength() })); @@ -876,6 +888,9 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES // initiatorResumeMIC ); + // the PacketBufferHandler should be empty + VerifyOrReturnError(msg.IsNull(), CHIP_ERROR_INCORRECT_STATE); + msg = System::PacketBufferHandle::New(data_len); VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); @@ -910,9 +925,64 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle && msg) { MATTER_TRACE_SCOPE("HandleSigma1_and_SendSigma2", "CASESession"); - ReturnErrorOnFailure(HandleSigma1(std::move(msg))); - return CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + + // Parse and Validate Received Sigma1, and decide next step + SuccessOrExit(err = HandleSigma1(std::move(msg))); + + switch (mNextStep) + { + case Step::kSendSigma2: { + + System::PacketBufferHandle msg_R2; + EncodeSigma2Param encodeSigma2; + + // TODO verify MATTER_LOG_METRIC locations + MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); + + SuccessOrExit(err = PrepareSigma2(encodeSigma2)); + SuccessOrExit(err = EncodeSigma2(msg_R2, encodeSigma2)); + SuccessOrExitAction(err = SendSigma2(msg_R2), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2, err)); + + mDelegate->OnSessionEstablishmentStarted(); + break; + } + case Step::kSendSigma2Resume: { + + System::PacketBufferHandle msg_R2_resume; + EncodeSigma2ResParam encodeSigma2Resume; + + MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); + + SuccessOrExit(err = PrepareSigma2Resume(encodeSigma2Resume)); + SuccessOrExit(err = EncodeSigma2Resume(msg_R2_resume, encodeSigma2Resume)); + SuccessOrExitAction(err = SendSigma2Resume(msg_R2_resume), + MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2Resume, err)); + + mDelegate->OnSessionEstablishmentStarted(); + break; + } + // TODO should I keep this? + case Step::kSendStatusReport: + default: + ExitNow(); + break; + } + +exit: + + if (err == CHIP_ERROR_KEY_NOT_FOUND) + { + SendStatusReport(mExchangeCtxt, kProtocolCodeNoSharedRoot); + mState = State::kInitialized; + } + else if (err != CHIP_NO_ERROR) + { + SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam); + mState = State::kInitialized; + } + return err; } CHIP_ERROR CASESession::FindLocalNodeFromDestinationId(const ByteSpan & destinationId, const ByteSpan & initiatorRandom) @@ -1003,18 +1073,19 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) CHIP_ERROR err = CHIP_NO_ERROR; System::PacketBufferTLVReader tlvReader; + // Struct that will serve as output in ParseSigma1 ParseSigma1Param parsedSigma1; - SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); tlvReader.Init(std::move(msg)); - SuccessOrExit(err = ParseSigma1(tlvReader, parsedSigma1)); + ReturnErrorOnFailure(ParseSigma1(tlvReader, parsedSigma1)); ChipLogDetail(SecureChannel, "Peer assigned session key ID %d", parsedSigma1.initiatorSessionId); SetPeerSessionId(parsedSigma1.initiatorSessionId); - VerifyOrExit(mFabricsTable != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); // Set the MRP parameters provided in the Sigma1 message if (parsedSigma1.InitiatorMRPParamsPresent) @@ -1032,21 +1103,18 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) std::copy(parsedSigma1.initiatorRandom.begin(), parsedSigma1.initiatorRandom.end(), mInitiatorRandom); std::copy(parsedSigma1.resumptionId.begin(), parsedSigma1.resumptionId.end(), mResumeResumptionId.begin()); - // Send Sigma2Resume message to the initiator - MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); - err = SendSigma2Resume(); - if (CHIP_NO_ERROR != err) - { - MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2Resume, err); - } - SuccessOrExit(err); + // Next Step is to send Sigma2Resume message to the initiator + mNextStep = Step::kSendSigma2Resume; - mDelegate->OnSessionEstablishmentStarted(); - - // Early returning here, since we have sent Sigma2Resume, and no further processing is needed for the Sigma1 message + // Early returning here, since the next Step is known to be Sigma2Resume, and no further processing is needed for the + // Sigma1 message return CHIP_NO_ERROR; } + // ParseSigma1 ensures that: + // mRemotePubKey.Length() == initiatorPubKey.size() == kP256_PublicKey_Length. + memcpy(mRemotePubKey.Bytes(), parsedSigma1.initiatorEphPubKey.data(), mRemotePubKey.Length()); + // Attempt to match the initiator's desired destination based on local fabric table. err = FindLocalNodeFromDestinationId(parsedSigma1.destinationId, parsedSigma1.initiatorRandom); if (err == CHIP_NO_ERROR) @@ -1056,83 +1124,80 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) // Side-effect of FindLocalNodeFromDestinationId success was that mFabricIndex/mLocalNodeId are now // set to the local fabric and associated NodeId that was targeted by the initiator. + + mNextStep = Step::kSendSigma2; } else { ChipLogError(SecureChannel, "CASE failed to match destination ID with local fabrics"); ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); - } - SuccessOrExit(err); - // ParseSigma1 ensures that: - // mRemotePubKey.Length() == initiatorPubKey.size() == kP256_PublicKey_Length. - memcpy(mRemotePubKey.Bytes(), parsedSigma1.initiatorEphPubKey.data(), mRemotePubKey.Length()); + // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if validation of DestinationID fails, which will trigger + // should trigger status Report with ProtocolCode NoSharedTrustRoots. + mNextStep = Step::kSendStatusReport; - MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); - err = SendSigma2(); - if (CHIP_NO_ERROR != err) - { - MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2, err); + return err; } - SuccessOrExit(err); - mDelegate->OnSessionEstablishmentStarted(); + return CHIP_NO_ERROR; +} -exit: +CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResParam & output) +{ + MATTER_TRACE_SCOPE("PrepareSigma2Resume", "CASESession"); - if (err == CHIP_ERROR_KEY_NOT_FOUND) - { - SendStatusReport(mExchangeCtxt, kProtocolCodeNoSharedRoot); - mState = State::kInitialized; - } - else if (err != CHIP_NO_ERROR) - { - SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam); - mState = State::kInitialized; - } - return err; + // Validate that we have a session ID allocated. + VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); + output.responderSessionId = GetLocalSessionId().Value(); + + // Generate a new resumption ID + ReturnErrorOnFailure(DRBG_get_bytes(mNewResumptionId.data(), mNewResumptionId.size())); + output.resumptionId = mNewResumptionId; + + ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), mNewResumptionId, ByteSpan(kKDFS2RKeyInfo), + ByteSpan(kResume2MIC_Nonce), output.resumeMICSpan)); + + VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + output.responderMrpConfig = &mLocalMRPConfig.Value(); + + mState = State::kSentSigma2Resume; + + return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::SendSigma2Resume() +CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_resume, EncodeSigma2ResParam & input) { - MATTER_TRACE_SCOPE("SendSigma2Resume", "CASESession"); - size_t max_sigma2_resume_data_len = - TLV::EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, - sizeof(uint16_t), SessionParameters::kEstimatedTLVSize); + MATTER_TRACE_SCOPE("EncodeSigma2Resume", "CASESession"); + size_t max_sigma2_resume_data_len = TLV::EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, // sigma2ResumeMIC + sizeof(uint16_t), // responderSessionID + SessionParameters::kEstimatedTLVSize // responderSessionParams + ); System::PacketBufferTLVWriter tlvWriter; - System::PacketBufferHandle msg_R2_resume; TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; - // Validate that we have a session ID allocated. - VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); - msg_R2_resume = System::PacketBufferHandle::New(max_sigma2_resume_data_len); VerifyOrReturnError(!msg_R2_resume.IsNull(), CHIP_ERROR_NO_MEMORY); tlvWriter.Init(std::move(msg_R2_resume)); - // Generate a new resumption ID - ReturnErrorOnFailure(DRBG_get_bytes(mNewResumptionId.data(), mNewResumptionId.size())); - ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), mNewResumptionId)); - - uint8_t sigma2ResumeMIC[CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - MutableByteSpan resumeMICSpan(sigma2ResumeMIC); - ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), mNewResumptionId, ByteSpan(kKDFS2RKeyInfo), - ByteSpan(kResume2MIC_Nonce), resumeMICSpan)); - - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), resumeMICSpan)); - - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), GetLocalSessionId().Value())); - - VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(4), mLocalMRPConfig.Value(), tlvWriter)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResumptionID), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_Sigma2ResumeMIC), input.resumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResponderSessionID), input.responderSessionId)); + ReturnErrorOnFailure( + EncodeSessionParameters(TLV::ContextTag(kTag_Sigma2Res_ResponderMRPParams), *input.responderMrpConfig, tlvWriter)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R2_resume)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR CASESession::SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume) +{ + // Call delegate to send the msg to peer ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma2Resume, std::move(msg_R2_resume), @@ -1145,11 +1210,13 @@ CHIP_ERROR CASESession::SendSigma2Resume() return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::SendSigma2() +CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Param & output) { - MATTER_TRACE_SCOPE("SendSigma2", "CASESession"); + MATTER_TRACE_SCOPE("PrepareSigma2", "CASESession"); VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); + output.responderSessionId = GetLocalSessionId().Value(); + VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); chip::Platform::ScopedMemoryBuffer icacBuf; @@ -1165,13 +1232,13 @@ CHIP_ERROR CASESession::SendSigma2() ReturnErrorOnFailure(mFabricsTable->FetchNOCCert(mFabricIndex, nocCert)); // Fill in the random value - uint8_t msg_rand[kSigmaParamRandomNumberSize]; - ReturnErrorOnFailure(DRBG_get_bytes(&msg_rand[0], sizeof(msg_rand))); + ReturnErrorOnFailure(DRBG_get_bytes(&output.responderRandom[0], sizeof(output.responderRandom))); // Generate an ephemeral keypair mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); + output.pEphPubKey = &mEphemeralKey->Pubkey(); // Generate a Shared Secret ReturnErrorOnFailure(mEphemeralKey->ECDH_derive_secret(mRemotePubKey, mSharedSecret)); @@ -1179,14 +1246,17 @@ CHIP_ERROR CASESession::SendSigma2() uint8_t msg_salt[kIPKSize + kSigmaParamRandomNumberSize + kP256_PublicKey_Length + kSHA256_Hash_Length]; MutableByteSpan saltSpan(msg_salt); - ReturnErrorOnFailure(ConstructSaltSigma2(ByteSpan(msg_rand), mEphemeralKey->Pubkey(), ByteSpan(mIPK), saltSpan)); + ReturnErrorOnFailure(ConstructSaltSigma2(ByteSpan(output.responderRandom), mEphemeralKey->Pubkey(), ByteSpan(mIPK), saltSpan)); AutoReleaseSessionKey sr2k(*mSessionManager->GetSessionKeystore()); ReturnErrorOnFailure(DeriveSigmaKey(saltSpan, ByteSpan(kKDFSR2Info), sr2k)); // Construct Sigma2 TBS Data - size_t msg_r2_signed_len = - TLV::EstimateStructOverhead(kMaxCHIPCertLength, kMaxCHIPCertLength, kP256_PublicKey_Length, kP256_PublicKey_Length); + size_t msg_r2_signed_len = TLV::EstimateStructOverhead(kMaxCHIPCertLength, // responderNoc + kMaxCHIPCertLength, // responderICAC + kP256_PublicKey_Length, // responderEphPubKey + kP256_PublicKey_Length // InitiatorEphPubKey + ); chip::Platform::ScopedMemoryBuffer msg_R2_Signed; VerifyOrReturnError(msg_R2_Signed.Alloc(msg_r2_signed_len), CHIP_ERROR_NO_MEMORY); @@ -1201,16 +1271,19 @@ CHIP_ERROR CASESession::SendSigma2() msg_R2_Signed.Free(); // Construct Sigma2 TBE Data - size_t msg_r2_signed_enc_len = TLV::EstimateStructOverhead(nocCert.size(), icaCert.size(), tbsData2Signature.Length(), - SessionResumptionStorage::kResumptionIdSize); + size_t msg_r2_signed_enc_len = TLV::EstimateStructOverhead(nocCert.size(), // responderNoc + icaCert.size(), // responderICAC + tbsData2Signature.Length(), // signature + SessionResumptionStorage::kResumptionIdSize // resumptionID + ); - chip::Platform::ScopedMemoryBuffer msg_R2_Encrypted; - VerifyOrReturnError(msg_R2_Encrypted.Alloc(msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES), CHIP_ERROR_NO_MEMORY); + VerifyOrReturnError(output.msg_R2_Encrypted.Alloc(msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES), + CHIP_ERROR_NO_MEMORY); TLV::TLVWriter tlvWriter; TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; - tlvWriter.Init(msg_R2_Encrypted.Get(), msg_r2_signed_enc_len); + tlvWriter.Init(output.msg_R2_Encrypted.Get(), msg_r2_signed_enc_len); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_SenderNOC), nocCert)); if (!icaCert.empty()) @@ -1236,40 +1309,70 @@ CHIP_ERROR CASESession::SendSigma2() ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); - msg_r2_signed_enc_len = static_cast(tlvWriter.GetLengthWritten()); - + msg_r2_signed_enc_len = static_cast(tlvWriter.GetLengthWritten()); + output.encrypted2Length = msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; // Generate the encrypted data blob - ReturnErrorOnFailure(AES_CCM_encrypt(msg_R2_Encrypted.Get(), msg_r2_signed_enc_len, nullptr, 0, sr2k.KeyHandle(), - kTBEData2_Nonce, kTBEDataNonceLength, msg_R2_Encrypted.Get(), - msg_R2_Encrypted.Get() + msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); + ReturnErrorOnFailure(AES_CCM_encrypt(output.msg_R2_Encrypted.Get(), msg_r2_signed_enc_len, nullptr, 0, sr2k.KeyHandle(), + kTBEData2_Nonce, kTBEDataNonceLength, output.msg_R2_Encrypted.Get(), + output.msg_R2_Encrypted.Get() + msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); - // Construct Sigma2 Msg - 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); + VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + output.responderMrpConfig = &mLocalMRPConfig.Value(); - System::PacketBufferHandle msg_R2 = System::PacketBufferHandle::New(data_len); + return CHIP_NO_ERROR; +} + +CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, EncodeSigma2Param & input) +{ + + size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, // responderRandom + sizeof(uint16_t), // responderSessionId + kP256_PublicKey_Length, // responderEphPubKey + input.encrypted2Length, // encrypted2 + SessionParameters::kEstimatedTLVSize // responderSessionParams + ); + + // the PacketBufferHandler should be empty + VerifyOrReturnError(msg_R2.IsNull(), CHIP_ERROR_INCORRECT_STATE); + + msg_R2 = System::PacketBufferHandle::New(data_len); VerifyOrReturnError(!msg_R2.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriterMsg2; - outerContainerType = TLV::kTLVType_NotSpecified; + TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; tlvWriterMsg2.Init(std::move(msg_R2)); ReturnErrorOnFailure(tlvWriterMsg2.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(1), &msg_rand[0], sizeof(msg_rand))); - ReturnErrorOnFailure(tlvWriterMsg2.Put(TLV::ContextTag(2), GetLocalSessionId().Value())); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(3), mEphemeralKey->Pubkey(), - static_cast(mEphemeralKey->Pubkey().Length()))); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(4), msg_R2_Encrypted.Get(), - static_cast(msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES))); - VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig.Value(), tlvWriterMsg2)); + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_ResponderRandom), &input.responderRandom[0], + sizeof(input.responderRandom))); + ReturnErrorOnFailure(tlvWriterMsg2.Put(TLV::ContextTag(kTag_Sigma2_ResponderSessionId), input.responderSessionId)); + + VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_ResponderEphPubKey), *input.pEphPubKey, + static_cast(input.pEphPubKey->Length()))); + + // Check if msg_R2_Encrypted is not nullptr + VerifyOrReturnError(input.msg_R2_Encrypted, CHIP_ERROR_INCORRECT_STATE); + + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_Encrypted2), input.msg_R2_Encrypted.Get(), + static_cast(input.encrypted2Length))); + + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure( + EncodeSessionParameters(TLV::ContextTag(kTag_Sigma2_ResponderMRPParams), *input.responderMrpConfig, tlvWriterMsg2)); ReturnErrorOnFailure(tlvWriterMsg2.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msg_R2)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR CASESession::SendSigma2(System::PacketBufferHandle & msg_R2) +{ + MATTER_TRACE_SCOPE("SendSigma2", "CASESession"); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R2->Start(), msg_R2->DataLength() })); // Call delegate to send the msg to peer diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 4464423da151ce..bd0d6b7de28215 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -146,10 +146,17 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, bool InitiatorMRPParamsPresent = false; }; - /* - * TLV Encodes a Sigma1 message into the payload handled by msg - */ - CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Param & InputEncodeSigma1); + /** + * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inparam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outmsg` must be in a null state. + **/ + CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outmsg, EncodeSigma1Param & inparam); /** * Parse a sigma1 message. This function will return success only if the @@ -161,16 +168,67 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * * Either resumptionID and initiatorResume1MIC are both present or both * absent. * - * On success, the initiatorRandom, initiatorSessionId, destinationId, - * initiatorEphPubKey outparams will be set to the corresponding values in - * the message. + * On success, the members of outparam will be set to the values corresponding to the message. * - * On success, either the resumptionRequested outparam will be set to true - * and the resumptionID and initiatorResumeMIC outparams will be set to - * valid values, or the resumptionRequested outparam will be set to false. + * On success, either the sessionResumptionRequested outparam will be set to true + * and the resumptionID and initiatorResumeMICSpan outparams will be set to + * valid values, or the sessionResumptionRequested outparam will be set to false. */ - CHIP_ERROR - ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & OutputParseSigma1); + CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & outparam); + + enum class Step : uint8_t + { + kNone, + kSendSigma2, + kSendSigma2Resume, + kSendStatusReport + }; + + Step mNextStep = Step::kNone; + + struct EncodeSigma2Param + { + uint8_t responderRandom[kSigmaParamRandomNumberSize]; + uint16_t responderSessionId; + const Crypto::P256PublicKey * pEphPubKey; + Platform::ScopedMemoryBuffer msg_R2_Encrypted; + size_t encrypted2Length; + const ReliableMessageProtocolConfig * responderMrpConfig; + }; + + struct EncodeSigma2ResParam + { + ByteSpan resumptionId; + uint8_t sigma2ResumeMIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + MutableByteSpan resumeMICSpan{ sigma2ResumeMIC }; + uint16_t responderSessionId; + const ReliableMessageProtocolConfig * responderMrpConfig; + }; + + /** + * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inparam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outmsg` must be in a null state. + **/ + + CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outmsg, EncodeSigma2Param & inparam); + + /** + * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inparam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outmsg` must be in a null state. + **/ + CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outmsg, EncodeSigma2ResParam & inparam); /** * @brief @@ -273,7 +331,12 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR HandleSigma1(System::PacketBufferHandle && msg); CHIP_ERROR TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC, ByteSpan initiatorRandom); - CHIP_ERROR SendSigma2(); + + CHIP_ERROR PrepareSigma2(EncodeSigma2Param & output); + CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResParam & output); + CHIP_ERROR SendSigma2(System::PacketBufferHandle & msg_R2); + CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume); + CHIP_ERROR HandleSigma2_and_SendSigma3(System::PacketBufferHandle && msg); CHIP_ERROR HandleSigma2(System::PacketBufferHandle && msg); CHIP_ERROR HandleSigma2Resume(System::PacketBufferHandle && msg); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index ccc4f142a03c51..5e3f90e3313317 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -867,6 +867,178 @@ TEST_F(TestCASESession, Sigma1ParsingTest) TestSigma1Parsing(mem, bufferSize, Sigma1SessionIdTooBig); } +TEST_F(TestCASESession, EncodeSigma1Test) +{ + System::PacketBufferHandle msg; + CASESession session; + CASESession::EncodeSigma1Param encodeParams; + + uint8_t random[32]; + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], 32), CHIP_NO_ERROR); + encodeParams.initiatorRandom = ByteSpan(random, sizeof(random)); + encodeParams.initiatorSessionId = 7315; + uint8_t destinationId[32] = { 0xDE, 0xAD }; + encodeParams.destinationId = ByteSpan(destinationId, sizeof(destinationId)); + + ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); + encodeParams.initiatorMrpConfig = &MRPConfig; + + // EncodeSigma1 should fail when there is no public key + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(msg, encodeParams)); + + // Free the PacketBuffer + msg = nullptr; + + Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); + ASSERT_NE(EphemeralKey, nullptr); + EXPECT_EQ(CHIP_NO_ERROR, EphemeralKey->Initialize(ECPKeyTarget::ECDH)); + encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + + // Succeed when Public Key is provided + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg, encodeParams)); + + // Free the PacketBuffer + msg = nullptr; + + // EncodeSigma1 should fail when MRP config is missing + encodeParams.initiatorMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(msg, encodeParams)); + + // Free the PacketBuffer + msg = nullptr; + + // Succeed when MRP Config is provided + encodeParams.initiatorMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg, encodeParams)); + + { + System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); + + // EncodeSigma1 should fail when the packetBufferHandle passed to it is not empty + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(nonEmptyMsg, encodeParams)); + } + + { + System::PacketBufferHandle msg1; + System::PacketBufferTLVReader tlvReader; + CASESession::ParseSigma1Param parseParams; + + // Round Trip Test: Encode Sigma1, Parse it then verify parsed values + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg1, encodeParams)); + + tlvReader.Init(std::move(msg1)); + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + + // compare parsed values with original values + EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); + EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); + EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); + EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( + ByteSpan(encodeParams.pEphPubKey->ConstBytes(), encodeParams.pEphPubKey->Length()))); + } + + { + System::PacketBufferHandle msg2; + System::PacketBufferTLVReader tlvReader; + CASESession::ParseSigma1Param parseParams; + + // Round Trip Test: Sigma1 with Session Resumption + // Encode Sigma1 with Resumption, parse it and and verify with original values + chip::SessionResumptionStorage::ResumptionIdStorage resumptionId; + + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(resumptionId.data(), resumptionId.size()), CHIP_NO_ERROR); + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.initiatorResume1MIC[0], sizeof(encodeParams.initiatorResume1MIC)), + CHIP_NO_ERROR); + + encodeParams.resumptionId = ByteSpan(resumptionId.data(), resumptionId.size()); + encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MIC); + encodeParams.sessionResumptionRequested = true; + + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg2, encodeParams)); + + // Encode and Parse Round Trip Test + tlvReader.Init(std::move(msg2)); + + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + + // RoundTrip + EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); + EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); + EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); + EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( + ByteSpan(encodeParams.pEphPubKey->ConstBytes(), encodeParams.pEphPubKey->Length()))); + + EXPECT_TRUE(parseParams.resumptionId.data_equal(encodeParams.resumptionId)); + EXPECT_TRUE(parseParams.initiatorResumeMICSpan.data_equal(encodeParams.initiatorResumeMICSpan)); + EXPECT_TRUE(parseParams.InitiatorMRPParamsPresent); + } + // Release EphemeralKeyPair + gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); +} + +TEST_F(TestCASESession, EncodeSigma2Test) +{ + System::PacketBufferHandle msg; + CASESession session; + CASESession::EncodeSigma2Param encodeParams; + + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); + encodeParams.responderSessionId = 7315; + + // Generate Ephemeral Public Key + Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); + ASSERT_NE(EphemeralKey, nullptr); + EXPECT_EQ(CHIP_NO_ERROR, EphemeralKey->Initialize(ECPKeyTarget::ECDH)); + encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + + // TBEData2Encrypted + encodeParams.msg_R2_Encrypted.Alloc(100); + + // responder Session Parameters + ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); + encodeParams.responderMrpConfig = &MRPConfig; + + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + + { + System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); + + // EncodeSigma2 should fail when the packetBufferHandle passed to it is not empty + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(nonEmptyMsg, encodeParams)); + } + + // EncodeSigma1 should fail when there is no public key + encodeParams.pEphPubKey = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); + msg = nullptr; + + encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + msg = nullptr; + + // EncodeSigma1 should fail when TBEData2Encrypted is not allocated + encodeParams.msg_R2_Encrypted.Free(); + + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); + msg = nullptr; + + encodeParams.msg_R2_Encrypted.Alloc(100); + + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + + // EncodeSigma1 should fail when MRP config is missing + encodeParams.responderMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); + msg = nullptr; + + // Succeed when MRP Config is provided + encodeParams.responderMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + + // Release EphemeralKeyPair + gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); +} + struct SessionResumptionTestStorage : SessionResumptionStorage { SessionResumptionTestStorage(CHIP_ERROR findMethodReturnCode, ScopedNodeId peerNodeId, ResumptionIdStorage * resumptionId, From 6c13347ca6c64ac08c86c2c8a9b2a3766e4fe8c6 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Thu, 12 Dec 2024 13:42:16 +0100 Subject: [PATCH 04/16] Adding Encrypted2 datalen check --- src/protocols/secure_channel/CASESession.cpp | 3 +++ src/protocols/secure_channel/CASESession.h | 8 ++++---- .../secure_channel/tests/TestCASESession.cpp | 14 ++++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index be7f667311def7..7c352e21cbef8b 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -1356,6 +1356,9 @@ CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, Encode // Check if msg_R2_Encrypted is not nullptr VerifyOrReturnError(input.msg_R2_Encrypted, CHIP_ERROR_INCORRECT_STATE); + // Check if length of msg_R2_Encrypted is set and is at least larger than the MIC length + VerifyOrReturnError(input.encrypted2Length > CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_Encrypted2), input.msg_R2_Encrypted.Get(), static_cast(input.encrypted2Length))); diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 69123c82dc6add..c147bb23d60eae 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -135,8 +135,8 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, struct EncodeSigma1Param : Sigma1Param { - const Crypto::P256PublicKey * pEphPubKey; - const ReliableMessageProtocolConfig * initiatorMrpConfig; + const Crypto::P256PublicKey * pEphPubKey = nullptr; + const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr; uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; }; @@ -191,9 +191,9 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, { uint8_t responderRandom[kSigmaParamRandomNumberSize]; uint16_t responderSessionId; - const Crypto::P256PublicKey * pEphPubKey; + const Crypto::P256PublicKey * pEphPubKey = nullptr; Platform::ScopedMemoryBuffer msg_R2_Encrypted; - size_t encrypted2Length; + size_t encrypted2Length = 0; const ReliableMessageProtocolConfig * responderMrpConfig; }; diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 5e3f90e3313317..7bfbb2a6144a5d 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -981,6 +981,7 @@ TEST_F(TestCASESession, EncodeSigma2Test) System::PacketBufferHandle msg; CASESession session; CASESession::EncodeSigma2Param encodeParams; + constexpr uint8_t kEncrypted2datalen = 100U; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); encodeParams.responderSessionId = 7315; @@ -992,7 +993,8 @@ TEST_F(TestCASESession, EncodeSigma2Test) encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); // TBEData2Encrypted - encodeParams.msg_R2_Encrypted.Alloc(100); + encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; + encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); // responder Session Parameters ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); @@ -1022,10 +1024,18 @@ TEST_F(TestCASESession, EncodeSigma2Test) EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); msg = nullptr; - encodeParams.msg_R2_Encrypted.Alloc(100); + encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + // EncodeSigma1 should fail when the encrypted2Length is not set + encodeParams.encrypted2Length = 0; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); + msg = nullptr; + + // Set encrypted2Length again + encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; + // EncodeSigma1 should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); From 5673728513d639e77d456c9859a13ef1e3216d83 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 13 Dec 2024 11:43:05 +0100 Subject: [PATCH 05/16] renaming variables --- src/protocols/secure_channel/CASESession.cpp | 18 ++++---- src/protocols/secure_channel/CASESession.h | 42 +++++++++---------- .../secure_channel/tests/TestCASESession.cpp | 16 +++---- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 7c352e21cbef8b..cf39a7e0b7f112 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -783,7 +783,7 @@ CHIP_ERROR CASESession::SendSigma1() uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; // Struct that will be used as input to EncodeSigma1() method - EncodeSigma1Param encodeSigma1Params; + EncodeSigma1Inputs encodeSigma1Params; // Lookup fabric info. const auto * fabricInfo = mFabricsTable->FindFabricWithIndex(mFabricIndex); @@ -874,7 +874,7 @@ CHIP_ERROR CASESession::SendSigma1() return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Param & input) +CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Inputs & input) { MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); @@ -936,7 +936,7 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & case Step::kSendSigma2: { System::PacketBufferHandle msg_R2; - EncodeSigma2Param encodeSigma2; + EncodeSigma2Inputs encodeSigma2; // TODO verify MATTER_LOG_METRIC locations MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); @@ -1074,7 +1074,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) System::PacketBufferTLVReader tlvReader; // Struct that will serve as output in ParseSigma1 - ParseSigma1Param parsedSigma1; + ParsedSigma1 parsedSigma1; ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); @@ -1088,7 +1088,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); // Set the MRP parameters provided in the Sigma1 message - if (parsedSigma1.InitiatorMRPParamsPresent) + if (parsedSigma1.initiatorMrpParamsPresent) { mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( GetRemoteSessionParameters()); @@ -1210,7 +1210,7 @@ CHIP_ERROR CASESession::SendSigma2Resume(System::PacketBufferHandle & msg_R2_res return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Param & output) +CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) { MATTER_TRACE_SCOPE("PrepareSigma2", "CASESession"); @@ -1322,7 +1322,7 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Param & output) return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, EncodeSigma2Param & input) +CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, EncodeSigma2Inputs & input) { size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, // responderRandom @@ -2294,7 +2294,7 @@ CHIP_ERROR CASESession::OnFailureStatusReport(Protocols::SecureChannel::GeneralS return err; } -CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & output) +CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & output) { using namespace TLV; @@ -2322,7 +2322,7 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kInitiatorMRPParamsTag)) { ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(kInitiatorMRPParamsTag), tlvReader)); - output.InitiatorMRPParamsPresent = true; + output.initiatorMrpParamsPresent = true; err = tlvReader.Next(); } diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index c147bb23d60eae..9a9e0bfac49bf3 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -133,30 +133,30 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, ByteSpan initiatorResumeMICSpan; }; - struct EncodeSigma1Param : Sigma1Param + struct EncodeSigma1Inputs : Sigma1Param { const Crypto::P256PublicKey * pEphPubKey = nullptr; const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr; uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; }; - struct ParseSigma1Param : Sigma1Param + struct ParsedSigma1 : Sigma1Param { ByteSpan initiatorEphPubKey; - bool InitiatorMRPParamsPresent = false; + bool initiatorMrpParamsPresent = false; }; /** * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. * - * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. * - * @param inparam a struct containing all the values that will be encoded into TLV format + * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outmsg` must be in a null state. + * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ - CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outmsg, EncodeSigma1Param & inparam); + CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); /** * Parse a sigma1 message. This function will return success only if the @@ -168,13 +168,13 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * * Either resumptionID and initiatorResume1MIC are both present or both * absent. * - * On success, the members of outparam will be set to the values corresponding to the message. + * On success, the members of outParam will be set to the values corresponding to the message. * - * On success, either the sessionResumptionRequested outparam will be set to true + * On success, either the sessionResumptionRequested outParam will be set to true * and the resumptionID and initiatorResumeMICSpan outparams will be set to - * valid values, or the sessionResumptionRequested outparam will be set to false. + * valid values, or the sessionResumptionRequested outParam will be set to false. */ - CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParseSigma1Param & outparam); + CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam); // Helper Enum for usage in HandleSigma1_and_SendSigma2 enum class Step : uint8_t @@ -187,7 +187,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, Step mNextStep = Step::kNone; - struct EncodeSigma2Param + struct EncodeSigma2Inputs { uint8_t responderRandom[kSigmaParamRandomNumberSize]; uint16_t responderSessionId; @@ -209,27 +209,27 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, /** * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. * - * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. * - * @param inparam a struct containing all the values that will be encoded into TLV format + * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outmsg` must be in a null state. + * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ - CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outmsg, EncodeSigma2Param & inparam); + CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); /** * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. * - * @param outmsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. * - * @param inparam a struct containing all the values that will be encoded into TLV format + * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outmsg` must be in a null state. + * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ - CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outmsg, EncodeSigma2ResParam & inparam); + CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResParam & inParam); /** * @brief @@ -333,7 +333,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC, ByteSpan initiatorRandom); - CHIP_ERROR PrepareSigma2(EncodeSigma2Param & output); + CHIP_ERROR PrepareSigma2(EncodeSigma2Inputs & output); CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResParam & output); CHIP_ERROR SendSigma2(System::PacketBufferHandle & msg_R2); CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 7bfbb2a6144a5d..c61204b95d828f 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -745,7 +745,7 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - CASESession::ParseSigma1Param parsedSigma1; \ + CASESession::ParsedSigma1 parsedSigma1; \ CASESession session; \ \ EXPECT_EQ(session.ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ @@ -871,7 +871,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg; CASESession session; - CASESession::EncodeSigma1Param encodeParams; + CASESession::EncodeSigma1Inputs encodeParams; uint8_t random[32]; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], 32), CHIP_NO_ERROR); @@ -921,7 +921,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg1; System::PacketBufferTLVReader tlvReader; - CASESession::ParseSigma1Param parseParams; + CASESession::ParsedSigma1 parseParams; // Round Trip Test: Encode Sigma1, Parse it then verify parsed values EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg1, encodeParams)); @@ -940,7 +940,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg2; System::PacketBufferTLVReader tlvReader; - CASESession::ParseSigma1Param parseParams; + CASESession::ParsedSigma1 parseParams; // Round Trip Test: Sigma1 with Session Resumption // Encode Sigma1 with Resumption, parse it and and verify with original values @@ -970,7 +970,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) EXPECT_TRUE(parseParams.resumptionId.data_equal(encodeParams.resumptionId)); EXPECT_TRUE(parseParams.initiatorResumeMICSpan.data_equal(encodeParams.initiatorResumeMICSpan)); - EXPECT_TRUE(parseParams.InitiatorMRPParamsPresent); + EXPECT_TRUE(parseParams.initiatorMrpParamsPresent); } // Release EphemeralKeyPair gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); @@ -980,7 +980,7 @@ TEST_F(TestCASESession, EncodeSigma2Test) { System::PacketBufferHandle msg; CASESession session; - CASESession::EncodeSigma2Param encodeParams; + CASESession::EncodeSigma2Inputs encodeParams; constexpr uint8_t kEncrypted2datalen = 100U; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); @@ -1053,8 +1053,8 @@ struct SessionResumptionTestStorage : SessionResumptionStorage { SessionResumptionTestStorage(CHIP_ERROR findMethodReturnCode, ScopedNodeId peerNodeId, ResumptionIdStorage * resumptionId, Crypto::P256ECDHDerivedSecret * sharedSecret) : - mFindMethodReturnCode(findMethodReturnCode), - mPeerNodeId(peerNodeId), mResumptionId(resumptionId), mSharedSecret(sharedSecret) + mFindMethodReturnCode(findMethodReturnCode), mPeerNodeId(peerNodeId), mResumptionId(resumptionId), + mSharedSecret(sharedSecret) {} SessionResumptionTestStorage(CHIP_ERROR findMethodReturnCode) : mFindMethodReturnCode(findMethodReturnCode) {} CHIP_ERROR FindByScopedNodeId(const ScopedNodeId & node, ResumptionIdStorage & resumptionId, From 2722dc5caed81138e3ebcfe2d369042f8686f2e0 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 13 Dec 2024 13:19:42 +0100 Subject: [PATCH 06/16] Making Parsing and Encoding methods protected --- src/protocols/secure_channel/CASESession.cpp | 16 +- src/protocols/secure_channel/CASESession.h | 120 +++++++-------- .../secure_channel/tests/TestCASESession.cpp | 142 ++++++++++++------ 3 files changed, 169 insertions(+), 109 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index cf39a7e0b7f112..91ed9bffe052f8 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -951,7 +951,7 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & case Step::kSendSigma2Resume: { System::PacketBufferHandle msg_R2_resume; - EncodeSigma2ResParam encodeSigma2Resume; + EncodeSigma2ResInputs encodeSigma2Resume; MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); @@ -1142,7 +1142,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResParam & output) +CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResInputs & output) { MATTER_TRACE_SCOPE("PrepareSigma2Resume", "CASESession"); @@ -1165,7 +1165,7 @@ CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResParam & output) return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_resume, EncodeSigma2ResParam & input) +CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_resume, EncodeSigma2ResInputs & input) { MATTER_TRACE_SCOPE("EncodeSigma2Resume", "CASESession"); size_t max_sigma2_resume_data_len = TLV::EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID @@ -1174,18 +1174,24 @@ CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_r SessionParameters::kEstimatedTLVSize // responderSessionParams ); - System::PacketBufferTLVWriter tlvWriter; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + // the passed PacketBufferHandler should be empty + VerifyOrReturnError(msg_R2_resume.IsNull(), CHIP_ERROR_INCORRECT_STATE); msg_R2_resume = System::PacketBufferHandle::New(max_sigma2_resume_data_len); VerifyOrReturnError(!msg_R2_resume.IsNull(), CHIP_ERROR_NO_MEMORY); + System::PacketBufferTLVWriter tlvWriter; + TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + tlvWriter.Init(std::move(msg_R2_resume)); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResumptionID), input.resumptionId)); ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_Sigma2ResumeMIC), input.resumeMICSpan)); ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResponderSessionID), input.responderSessionId)); + + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure( EncodeSessionParameters(TLV::ContextTag(kTag_Sigma2Res_ResponderMRPParams), *input.responderMrpConfig, tlvWriter)); diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 9a9e0bfac49bf3..16ceee2a535f11 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -51,10 +51,6 @@ namespace chip { -namespace Testing { -class FuzzCASESession; -} - // TODO: temporary derive from Messaging::UnsolicitedMessageHandler, actually the CASEServer should be the umh, it will be fixed // when implementing concurrent CASE session. class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, @@ -146,36 +142,6 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, bool initiatorMrpParamsPresent = false; }; - /** - * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. - * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. - * - * @param inParam a struct containing all the values that will be encoded into TLV format - * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. - **/ - CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); - - /** - * Parse a sigma1 message. This function will return success only if the - * message passes schema checks. Specifically: - * * The tags come in order. - * * The required tags are present. - * * The values for the tags that are present satisfy schema requirements - * (e.g. constraints on octet string lengths) - * * Either resumptionID and initiatorResume1MIC are both present or both - * absent. - * - * On success, the members of outParam will be set to the values corresponding to the message. - * - * On success, either the sessionResumptionRequested outParam will be set to true - * and the resumptionID and initiatorResumeMICSpan outparams will be set to - * valid values, or the sessionResumptionRequested outParam will be set to false. - */ - CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam); - // Helper Enum for usage in HandleSigma1_and_SendSigma2 enum class Step : uint8_t { @@ -197,7 +163,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, const ReliableMessageProtocolConfig * responderMrpConfig; }; - struct EncodeSigma2ResParam + struct EncodeSigma2ResInputs { ByteSpan resumptionId; uint8_t sigma2ResumeMIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; @@ -206,31 +172,6 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, const ReliableMessageProtocolConfig * responderMrpConfig; }; - /** - * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. - * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. - * - * @param inParam a struct containing all the values that will be encoded into TLV format - * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. - **/ - - CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); - - /** - * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. - * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. - * - * @param inParam a struct containing all the values that will be encoded into TLV format - * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. - **/ - CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResParam & inParam); - /** * @brief * Derive a secure session from the established session. The API will return error if called before session is established. @@ -303,9 +244,64 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, // If this function returns true, the CASE session has been reset and is ready for a new session establishment. bool InvokeBackgroundWorkWatchdog(); +protected: + /** + * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inParam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outMsg` must be in a null state. + **/ + CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); + + /** + * Parse a sigma1 message. This function will return success only if the + * message passes schema checks. Specifically: + * * The tags come in order. + * * The required tags are present. + * * The values for the tags that are present satisfy schema requirements + * (e.g. constraints on octet string lengths) + * * Either resumptionID and initiatorResume1MIC are both present or both + * absent. + * + * On success, the members of outParam will be set to the values corresponding to the message. + * + * On success, either the sessionResumptionRequested outParam will be set to true + * and the resumptionID and initiatorResumeMICSpan outparams will be set to + * valid values, or the sessionResumptionRequested outParam will be set to false. + */ + CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam); + + /** + * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inParam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outMsg` must be in a null state. + **/ + + CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); + + /** + * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * + * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, + * as a new buffer will be allocated and assigned to it within the method. + * + * @param inParam a struct containing all the values that will be encoded into TLV format + * + * @note the passed PacketBufferHandle `outMsg` must be in a null state. + **/ + CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResInputs & inParam); + private: friend class TestCASESession; - friend class Testing::FuzzCASESession; using AutoReleaseSessionKey = Crypto::AutoReleaseSymmetricKey; @@ -334,7 +330,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, ByteSpan initiatorRandom); CHIP_ERROR PrepareSigma2(EncodeSigma2Inputs & output); - CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResParam & output); + CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResInputs & output); CHIP_ERROR SendSigma2(System::PacketBufferHandle & msg_R2); CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index c61204b95d828f..1ff82163a50e1c 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -80,6 +80,32 @@ class TestCASESession : public Test::LoopbackMessagingContext void SimulateUpdateNOCInvalidatePendingEstablishment(); }; +// CASESession Wrapper to Test the protected Functions +class CASESessionWrapper : public CASESession +{ +public: + CHIP_ERROR ParseSigma1Access(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam) + { + return ParseSigma1(tlvReader, outParam); + } + + CHIP_ERROR EncodeSigma1Access(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam) + { + return EncodeSigma1(outMsg, inParam); + } + + CHIP_ERROR EncodeSigma2Access(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam) + + { + return EncodeSigma2(outMsg, inParam); + } + + CHIP_ERROR EncodeSigma2ResumeAccess(System::PacketBufferHandle & outMsg, EncodeSigma2ResInputs & inParam) + { + return EncodeSigma2Resume(outMsg, inParam); + } +}; + void TestCASESession::ServiceEvents() { // Takes a few rounds of this because handling IO messages may schedule work, @@ -686,7 +712,7 @@ TEST_F(TestCASESession, DestinationIdTest) } template -static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) +static CHIP_ERROR EncodeSigma1Helper(MutableByteSpan & buf) { using namespace TLV; @@ -741,14 +767,14 @@ static CHIP_ERROR EncodeSigma1(MutableByteSpan & buf) do \ { \ MutableByteSpan buf(mem.Get(), bufferSize); \ - EXPECT_EQ(EncodeSigma1(buf), CHIP_NO_ERROR); \ + EXPECT_EQ(EncodeSigma1Helper(buf), CHIP_NO_ERROR); \ \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - CASESession::ParsedSigma1 parsedSigma1; \ - CASESession session; \ + CASESessionWrapper::ParsedSigma1 parsedSigma1; \ + CASESessionWrapper session; \ \ - EXPECT_EQ(session.ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ + EXPECT_EQ(session.ParseSigma1Access(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ if (params::expectSuccess) \ { \ EXPECT_EQ(parsedSigma1.sessionResumptionRequested, \ @@ -870,8 +896,8 @@ TEST_F(TestCASESession, Sigma1ParsingTest) TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg; - CASESession session; - CASESession::EncodeSigma1Inputs encodeParams; + CASESessionWrapper session; + CASESessionWrapper::EncodeSigma1Inputs encodeParams; uint8_t random[32]; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], 32), CHIP_NO_ERROR); @@ -884,10 +910,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.initiatorMrpConfig = &MRPConfig; // EncodeSigma1 should fail when there is no public key - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(msg, encodeParams)); - - // Free the PacketBuffer - msg = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(msg, encodeParams)); Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); ASSERT_NE(EphemeralKey, nullptr); @@ -895,39 +918,39 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); // Succeed when Public Key is provided - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg, encodeParams)); // Free the PacketBuffer msg = nullptr; // EncodeSigma1 should fail when MRP config is missing encodeParams.initiatorMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(msg, encodeParams)); // Free the PacketBuffer msg = nullptr; // Succeed when MRP Config is provided encodeParams.initiatorMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg, encodeParams)); { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma1 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(nonEmptyMsg, encodeParams)); } { System::PacketBufferHandle msg1; System::PacketBufferTLVReader tlvReader; - CASESession::ParsedSigma1 parseParams; + CASESessionWrapper::ParsedSigma1 parseParams; // Round Trip Test: Encode Sigma1, Parse it then verify parsed values - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg1, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg1, encodeParams)); tlvReader.Init(std::move(msg1)); - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1Access(tlvReader, parseParams)); // compare parsed values with original values EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); @@ -940,7 +963,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg2; System::PacketBufferTLVReader tlvReader; - CASESession::ParsedSigma1 parseParams; + CASESessionWrapper::ParsedSigma1 parseParams; // Round Trip Test: Sigma1 with Session Resumption // Encode Sigma1 with Resumption, parse it and and verify with original values @@ -954,12 +977,12 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MIC); encodeParams.sessionResumptionRequested = true; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1(msg2, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg2, encodeParams)); // Encode and Parse Round Trip Test tlvReader.Init(std::move(msg2)); - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1Access(tlvReader, parseParams)); // RoundTrip EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); @@ -979,8 +1002,8 @@ TEST_F(TestCASESession, EncodeSigma1Test) TEST_F(TestCASESession, EncodeSigma2Test) { System::PacketBufferHandle msg; - CASESession session; - CASESession::EncodeSigma2Inputs encodeParams; + CASESessionWrapper session; + CASESessionWrapper::EncodeSigma2Inputs encodeParams; constexpr uint8_t kEncrypted2datalen = 100U; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); @@ -1000,61 +1023,96 @@ TEST_F(TestCASESession, EncodeSigma2Test) ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + // free Buffer owned by PacketBufferHandle + msg = nullptr; { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma2 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(nonEmptyMsg, encodeParams)); } - // EncodeSigma1 should fail when there is no public key + // EncodeSigma2 should fail when there is no public key encodeParams.pEphPubKey = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); - msg = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); msg = nullptr; - // EncodeSigma1 should fail when TBEData2Encrypted is not allocated + // EncodeSigma2 should fail when TBEData2Encrypted is not allocated encodeParams.msg_R2_Encrypted.Free(); - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); - msg = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + msg = nullptr; - // EncodeSigma1 should fail when the encrypted2Length is not set + // EncodeSigma2 should fail when the encrypted2Length is not set encodeParams.encrypted2Length = 0; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); - msg = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); // Set encrypted2Length again encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; - // EncodeSigma1 should fail when MRP config is missing + // EncodeSigma2 should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); msg = nullptr; // Succeed when MRP Config is provided encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); // Release EphemeralKeyPair gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); } +TEST_F(TestCASESession, EncodeSigma2ResumeTest) +{ + System::PacketBufferHandle msg; + CASESessionWrapper session; + CASESessionWrapper::EncodeSigma2ResInputs encodeParams; + + encodeParams.responderSessionId = 7315; + + // responder Session Parameters + ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); + encodeParams.responderMrpConfig = &MRPConfig; + + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + // Free buffer owned by msg + msg = nullptr; + + { + System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); + + // EncodeSigma2Resume should fail when the packetBufferHandle passed to it is not empty + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2ResumeAccess(nonEmptyMsg, encodeParams)); + } + + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + msg = nullptr; + + // EncodeSigma2Resume should fail when MRP config is missing + encodeParams.responderMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + + // Succeed when MRP Config is provided + encodeParams.responderMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); +} + struct SessionResumptionTestStorage : SessionResumptionStorage { SessionResumptionTestStorage(CHIP_ERROR findMethodReturnCode, ScopedNodeId peerNodeId, ResumptionIdStorage * resumptionId, Crypto::P256ECDHDerivedSecret * sharedSecret) : - mFindMethodReturnCode(findMethodReturnCode), mPeerNodeId(peerNodeId), mResumptionId(resumptionId), - mSharedSecret(sharedSecret) + mFindMethodReturnCode(findMethodReturnCode), + mPeerNodeId(peerNodeId), mResumptionId(resumptionId), mSharedSecret(sharedSecret) {} SessionResumptionTestStorage(CHIP_ERROR findMethodReturnCode) : mFindMethodReturnCode(findMethodReturnCode) {} CHIP_ERROR FindByScopedNodeId(const ScopedNodeId & node, ResumptionIdStorage & resumptionId, @@ -1301,7 +1359,7 @@ TEST_F(TestCASESession, Sigma1BadDestinationIdTest) MutableByteSpan buf(data->Start(), data->AvailableDataLength()); // This uses a bogus destination id that is not going to match anything in practice. - EXPECT_EQ(EncodeSigma1(buf), CHIP_NO_ERROR); + EXPECT_EQ(EncodeSigma1Helper(buf), CHIP_NO_ERROR); data->SetDataLength(static_cast(buf.size())); Optional session = sessionManager.CreateUnauthenticatedSession(GetAliceAddress(), GetDefaultMRPConfig()); From ca802f18192c72f5cb911b9f547d15840459e986 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 13 Dec 2024 17:10:29 +0100 Subject: [PATCH 07/16] Converting TLV tags to enum class --- src/protocols/secure_channel/CASESession.cpp | 189 ++++++++++--------- 1 file changed, 101 insertions(+), 88 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 91ed9bffe052f8..bf10cb78af2538 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -51,56 +51,63 @@ namespace { -enum +enum class Sigma1Tags : uint8_t { - kTag_TBEData_SenderNOC = 1, - kTag_TBEData_SenderICAC = 2, - kTag_TBEData_Signature = 3, - kTag_TBEData_ResumptionID = 4, + kInitiatorRandom = 1, + kInitiatorSessionId = 2, + kDestinationId = 3, + kInitiatorPubKey = 4, + kInitiatorMRPParams = 5, + kResumptionID = 6, + kResume1MIC = 7, }; -enum +enum class TBEDataTags : uint8_t { - kTag_TBSData_SenderNOC = 1, - kTag_TBSData_SenderICAC = 2, - kTag_TBSData_SenderPubKey = 3, - kTag_TBSData_ReceiverPubKey = 4, + kSenderNOC = 1, + kSenderICAC = 2, + kSignature = 3, + kResumptionID = 4, }; -// Sigma1 TLV Tags -inline constexpr uint8_t kInitiatorRandomTag = 1; -inline constexpr uint8_t kInitiatorSessionIdTag = 2; -inline constexpr uint8_t kDestinationIdTag = 3; -inline constexpr uint8_t kInitiatorPubKeyTag = 4; -inline constexpr uint8_t kInitiatorMRPParamsTag = 5; -inline constexpr uint8_t kResumptionIDTag = 6; -inline constexpr uint8_t kResume1MICTag = 7; - -// Sigma2 TLV Tags -// TODO: either use constexpr, or enum for all -enum +enum class TBSDataTags : uint8_t { - kTag_Sigma2_ResponderRandom = 1, - kTag_Sigma2_ResponderSessionId = 2, - kTag_Sigma2_ResponderEphPubKey = 3, - kTag_Sigma2_Encrypted2 = 4, - kTag_Sigma2_ResponderMRPParams = 5, + kSenderNOC = 1, + kSenderICAC = 2, + kSenderPubKey = 3, + kReceiverPubKey = 4, }; -// Sigma2Resume TLV Tags -enum +enum class Sigma2Tags : uint8_t { - kTag_Sigma2Res_ResumptionID = 1, - kTag_Sigma2Res_Sigma2ResumeMIC = 2, - kTag_Sigma2Res_ResponderSessionID = 3, - kTag_Sigma2Res_ResponderMRPParams = 4, + kResponderRandom = 1, + kResponderSessionId = 2, + kResponderEphPubKey = 3, + kEncrypted2 = 4, + kResponderMRPParams = 5, }; -enum +enum class Sigma2ResTags : uint8_t { - kTag_Sigma3_Encrypted3 = 1, + + kResumptionID = 1, + kSigma2ResumeMIC = 2, + kResponderSessionID = 3, + kResponderMRPParams = 4, +}; + +enum class Sigma3Tags : uint8_t +{ + kEncrypted3 = 1, }; +// Utility to extract the underlying value of TLV Tag enum classes, used in TLV encoding and parsing. +template +constexpr auto ToRaw(Enum e) +{ + return static_cast>(e); +} + } // namespace namespace chip { @@ -899,21 +906,22 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig tlvWriter.Init(std::move(msg)); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorRandomTag), input.initiatorRandom)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kInitiatorSessionIdTag), input.initiatorSessionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kDestinationIdTag), input.destinationId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorRandom)), input.initiatorRandom)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorSessionId)), input.initiatorSessionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kDestinationId)), input.destinationId)); VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kInitiatorPubKeyTag), *input.pEphPubKey, + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorPubKey)), *input.pEphPubKey, static_cast(input.pEphPubKey->Length()))); VerifyOrReturnError(input.initiatorMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(kInitiatorMRPParamsTag), *input.initiatorMrpConfig, tlvWriter)); + ReturnErrorOnFailure( + EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams)), *input.initiatorMrpConfig, tlvWriter)); if (input.sessionResumptionRequested) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResumptionIDTag), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kResume1MICTag), input.initiatorResumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kResumptionID)), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kResume1MIC)), input.initiatorResumeMICSpan)); } ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); @@ -1133,7 +1141,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if validation of DestinationID fails, which will trigger - // should trigger status Report with ProtocolCode NoSharedTrustRoots. + // status Report with ProtocolCode = NoSharedTrustRoots. mNextStep = Step::kSendStatusReport; return err; @@ -1186,14 +1194,14 @@ CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_r tlvWriter.Init(std::move(msg_R2_resume)); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResumptionID), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_Sigma2ResumeMIC), input.resumeMICSpan)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_Sigma2Res_ResponderSessionID), input.responderSessionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kResumptionID)), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kSigma2ResumeMIC)), input.resumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kResponderSessionID)), input.responderSessionId)); VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure( - EncodeSessionParameters(TLV::ContextTag(kTag_Sigma2Res_ResponderMRPParams), *input.responderMrpConfig, tlvWriter)); + EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma2ResTags::kResponderMRPParams)), *input.responderMrpConfig, tlvWriter)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R2_resume)); @@ -1291,10 +1299,10 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) tlvWriter.Init(output.msg_R2_Encrypted.Get(), msg_r2_signed_enc_len); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_SenderNOC), nocCert)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)), nocCert)); if (!icaCert.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_SenderICAC), icaCert)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderICAC)), icaCert)); } // We are now done with ICAC and NOC certs so we can release the memory. @@ -1306,12 +1314,12 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) nocCert = MutableByteSpan{}; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), tbsData2Signature.ConstBytes(), + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(TBEDataTags::kSignature)), tbsData2Signature.ConstBytes(), static_cast(tbsData2Signature.Length()))); // Generate a new resumption ID ReturnErrorOnFailure(DRBG_get_bytes(mNewResumptionId.data(), mNewResumptionId.size())); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_ResumptionID), mNewResumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kResumptionID)), mNewResumptionId)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); @@ -1350,13 +1358,13 @@ CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, Encode tlvWriterMsg2.Init(std::move(msg_R2)); ReturnErrorOnFailure(tlvWriterMsg2.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_ResponderRandom), &input.responderRandom[0], + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderRandom)), &input.responderRandom[0], sizeof(input.responderRandom))); - ReturnErrorOnFailure(tlvWriterMsg2.Put(TLV::ContextTag(kTag_Sigma2_ResponderSessionId), input.responderSessionId)); + ReturnErrorOnFailure(tlvWriterMsg2.Put(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderSessionId)), input.responderSessionId)); VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_ResponderEphPubKey), *input.pEphPubKey, + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderEphPubKey)), *input.pEphPubKey, static_cast(input.pEphPubKey->Length()))); // Check if msg_R2_Encrypted is not nullptr @@ -1365,12 +1373,12 @@ CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, Encode // Check if length of msg_R2_Encrypted is set and is at least larger than the MIC length VerifyOrReturnError(input.encrypted2Length > CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(kTag_Sigma2_Encrypted2), input.msg_R2_Encrypted.Get(), + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kEncrypted2)), input.msg_R2_Encrypted.Get(), static_cast(input.encrypted2Length))); VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure( - EncodeSessionParameters(TLV::ContextTag(kTag_Sigma2_ResponderMRPParams), *input.responderMrpConfig, tlvWriterMsg2)); + EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderMRPParams)), *input.responderMrpConfig, tlvWriterMsg2)); ReturnErrorOnFailure(tlvWriterMsg2.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msg_R2)); @@ -1535,18 +1543,18 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = tlvReader.EnterContainer(containerType)); // Retrieve Responder's Random value - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_Sigma2_ResponderRandom))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderRandom)))); SuccessOrExit(err = tlvReader.GetBytes(responderRandom, sizeof(responderRandom))); // Assign Session ID - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_UnsignedInteger, TLV::ContextTag(kTag_Sigma2_ResponderSessionId))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_UnsignedInteger, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderSessionId)))); SuccessOrExit(err = tlvReader.Get(responderSessionId)); ChipLogDetail(SecureChannel, "Peer assigned session session ID %d", responderSessionId); SetPeerSessionId(responderSessionId); // Retrieve Responder's Ephemeral Pubkey - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_Sigma2_ResponderEphPubKey))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderEphPubKey)))); SuccessOrExit(err = tlvReader.GetBytes(mRemotePubKey, static_cast(mRemotePubKey.Length()))); // Generate a Shared Secret @@ -1562,7 +1570,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ buf, buflen })); // Generate decrypted data - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_Sigma2_Encrypted2))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kEncrypted2)))); max_msg_r2_signed_enc_len = TLV::EstimateStructOverhead(Credentials::kMaxCHIPCertLength, Credentials::kMaxCHIPCertLength, tbsData2Signature.Length(), @@ -1586,15 +1594,15 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = decryptedDataTlvReader.Next(containerType, TLV::AnonymousTag())); SuccessOrExit(err = decryptedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_SenderNOC))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)))); SuccessOrExit(err = decryptedDataTlvReader.Get(responderNOC)); SuccessOrExit(err = decryptedDataTlvReader.Next()); - if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_SenderICAC) + if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSenderICAC)) { VerifyOrExit(decryptedDataTlvReader.GetType() == TLV::kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); SuccessOrExit(err = decryptedDataTlvReader.Get(responderICAC)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_Signature))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSignature)))); } // Validate responder identity located in msg_r2_encrypted @@ -1621,7 +1629,8 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), msg_R2_Signed.Get(), msg_r2_signed_len)); - VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_Signature, err = CHIP_ERROR_INVALID_TLV_TAG); + VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSignature), + err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(tbsData2Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); tbsData2Signature.SetLength(decryptedDataTlvReader.GetLength()); SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData2Signature.Bytes(), tbsData2Signature.Length())); @@ -1630,7 +1639,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = responderPublicKey.ECDSA_validate_msg_signature(msg_R2_Signed.Get(), msg_r2_signed_len, tbsData2Signature)); // Retrieve session resumption ID - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_ResumptionID))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kResumptionID)))); SuccessOrExit(err = decryptedDataTlvReader.GetBytes(mNewResumptionId.data(), mNewResumptionId.size())); // Retrieve peer CASE Authenticated Tags (CATs) from peer's NOC. @@ -1639,7 +1648,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) // Retrieve responderMRPParams if present if (tlvReader.Next() != CHIP_END_OF_TLV) { - SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(kTag_Sigma2_ResponderMRPParams), tlvReader)); + SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderMRPParams)), tlvReader)); mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( GetRemoteSessionParameters()); } @@ -1758,10 +1767,10 @@ CHIP_ERROR CASESession::SendSigma3b(SendSigma3Data & data, bool & cancel) tlvWriter.Init(data.msg_R3_Encrypted.Get(), data.msg_r3_encrypted_len); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_SenderNOC), data.nocCert)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)), data.nocCert)); if (!data.icaCert.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBEData_SenderICAC), data.icaCert)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderICAC)), data.icaCert)); } // We are now done with ICAC and NOC certs so we can release the memory. @@ -1773,7 +1782,8 @@ CHIP_ERROR CASESession::SendSigma3b(SendSigma3Data & data, bool & cancel) data.nocCert = MutableByteSpan{}; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(kTag_TBEData_Signature), data.tbsData3Signature.ConstBytes(), + ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(TBEDataTags::kSignature)), + data.tbsData3Signature.ConstBytes(), static_cast(data.tbsData3Signature.Length()))); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); @@ -1914,7 +1924,7 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) max_msg_r3_signed_enc_len = TLV::EstimateStructOverhead(Credentials::kMaxCHIPCertLength, Credentials::kMaxCHIPCertLength, data.tbsData3Signature.Length(), kCaseOverheadForFutureTbeData); - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_Sigma3_Encrypted3))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma3Tags::kEncrypted3)))); msg_r3_encrypted_len_with_tag = tlvReader.GetLength(); @@ -1945,15 +1955,16 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) SuccessOrExit(err = decryptedDataTlvReader.Next(containerType, TLV::AnonymousTag())); SuccessOrExit(err = decryptedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_SenderNOC))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)))); SuccessOrExit(err = decryptedDataTlvReader.Get(data.initiatorNOC)); SuccessOrExit(err = decryptedDataTlvReader.Next()); - if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_SenderICAC) + if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSenderICAC)) { VerifyOrExit(decryptedDataTlvReader.GetType() == TLV::kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); SuccessOrExit(err = decryptedDataTlvReader.Get(data.initiatorICAC)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBEData_Signature))); + SuccessOrExit( + err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSignature)))); } // Step 4 - Construct Sigma3 TBS Data @@ -1966,7 +1977,7 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), data.msg_R3_Signed.Get(), data.msg_r3_signed_len)); - VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == kTag_TBEData_Signature, + VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSignature), err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(data.tbsData3Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); data.tbsData3Signature.SetLength(decryptedDataTlvReader.GetLength()); @@ -1993,12 +2004,14 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); SuccessOrExit(err = signedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBSData_SenderNOC))); + SuccessOrExit(err = + signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBSDataTags::kSenderNOC)))); SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorNOC)); if (!data.initiatorICAC.empty()) { - SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(kTag_TBSData_SenderICAC))); + SuccessOrExit( + err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBSDataTags::kSenderICAC)))); SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorICAC)); } } @@ -2189,13 +2202,13 @@ CHIP_ERROR CASESession::ConstructTBSData(const ByteSpan & senderNOC, const ByteS tlvWriter.Init(tbsData, tbsDataLen); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBSData_SenderNOC), senderNOC)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderNOC)), senderNOC)); if (!senderICAC.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBSData_SenderICAC), senderICAC)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderICAC)), senderICAC)); } - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBSData_SenderPubKey), senderPubKey)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kTag_TBSData_ReceiverPubKey), receiverPubKey)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderPubKey)), senderPubKey)); + ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kReceiverPubKey)), receiverPubKey)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); tbsDataLen = static_cast(tlvWriter.GetLengthWritten()); @@ -2308,26 +2321,26 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ReturnErrorOnFailure(tlvReader.Next(containerType, AnonymousTag())); ReturnErrorOnFailure(tlvReader.EnterContainer(containerType)); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorRandomTag))); + ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorRandom)))); ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorRandom)); VerifyOrReturnError(output.initiatorRandom.size() == kSigmaParamRandomNumberSize, CHIP_ERROR_INVALID_CASE_PARAMETER); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorSessionIdTag))); + ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorSessionId)))); ReturnErrorOnFailure(tlvReader.Get(output.initiatorSessionId)); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(kDestinationIdTag))); + ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kDestinationId)))); ReturnErrorOnFailure(tlvReader.GetByteView(output.destinationId)); VerifyOrReturnError(output.destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(kInitiatorPubKeyTag))); + ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorPubKey)))); ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorEphPubKey)); VerifyOrReturnError(output.initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); // Optional members start here. CHIP_ERROR err = tlvReader.Next(); - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kInitiatorMRPParamsTag)) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams))) { - ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(kInitiatorMRPParamsTag), tlvReader)); + ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams)), tlvReader)); output.initiatorMrpParamsPresent = true; err = tlvReader.Next(); @@ -2336,7 +2349,7 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, bool resumptionIDTagFound = false; bool resume1MICTagFound = false; - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kResumptionIDTag)) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kResumptionID))) { resumptionIDTagFound = true; ReturnErrorOnFailure(tlvReader.GetByteView(output.resumptionId)); @@ -2345,7 +2358,7 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, err = tlvReader.Next(); } - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(kResume1MICTag)) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kResume1MIC))) { resume1MICTagFound = true; ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorResumeMICSpan)); From d82be0a8100b90b95dc9462d641e036713a729c6 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 13 Dec 2024 19:13:14 +0100 Subject: [PATCH 08/16] Making structs protected and making Unit Test inherit CASESession --- src/protocols/secure_channel/CASESession.h | 108 +++++++++--------- .../secure_channel/tests/TestCASESession.cpp | 92 +++++---------- 2 files changed, 85 insertions(+), 115 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 16ceee2a535f11..1394df4eb37558 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -118,60 +118,6 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, */ void SetGroupDataProvider(Credentials::GroupDataProvider * groupDataProvider) { mGroupDataProvider = groupDataProvider; } - // This struct only serves as a base struct for EncodeSigma1 and ParseSigma1 - struct Sigma1Param - { - ByteSpan initiatorRandom; - uint16_t initiatorSessionId; - ByteSpan destinationId; - bool sessionResumptionRequested = false; - ByteSpan resumptionId; - ByteSpan initiatorResumeMICSpan; - }; - - struct EncodeSigma1Inputs : Sigma1Param - { - const Crypto::P256PublicKey * pEphPubKey = nullptr; - const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr; - uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - }; - - struct ParsedSigma1 : Sigma1Param - { - ByteSpan initiatorEphPubKey; - bool initiatorMrpParamsPresent = false; - }; - - // Helper Enum for usage in HandleSigma1_and_SendSigma2 - enum class Step : uint8_t - { - kNone, - kSendSigma2, - kSendSigma2Resume, - kSendStatusReport - }; - - Step mNextStep = Step::kNone; - - struct EncodeSigma2Inputs - { - uint8_t responderRandom[kSigmaParamRandomNumberSize]; - uint16_t responderSessionId; - const Crypto::P256PublicKey * pEphPubKey = nullptr; - Platform::ScopedMemoryBuffer msg_R2_Encrypted; - size_t encrypted2Length = 0; - const ReliableMessageProtocolConfig * responderMrpConfig; - }; - - struct EncodeSigma2ResInputs - { - ByteSpan resumptionId; - uint8_t sigma2ResumeMIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - MutableByteSpan resumeMICSpan{ sigma2ResumeMIC }; - uint16_t responderSessionId; - const ReliableMessageProtocolConfig * responderMrpConfig; - }; - /** * @brief * Derive a secure session from the established session. The API will return error if called before session is established. @@ -245,6 +191,60 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, bool InvokeBackgroundWorkWatchdog(); protected: + // Helper Enum for usage in HandleSigma1_and_SendSigma2 + enum class Step : uint8_t + { + kNone, + kSendSigma2, + kSendSigma2Resume, + kSendStatusReport + }; + + Step mNextStep = Step::kNone; + + // This struct only serves as a base struct for EncodeSigma1 and ParseSigma1 + struct Sigma1Param + { + ByteSpan initiatorRandom; + uint16_t initiatorSessionId; + ByteSpan destinationId; + bool sessionResumptionRequested = false; + ByteSpan resumptionId; + ByteSpan initiatorResumeMICSpan; + }; + + struct EncodeSigma1Inputs : Sigma1Param + { + const Crypto::P256PublicKey * pEphPubKey = nullptr; + const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr; + uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + }; + + struct ParsedSigma1 : Sigma1Param + { + ByteSpan initiatorEphPubKey; + bool initiatorMrpParamsPresent = false; + }; + + struct EncodeSigma2Inputs + { + uint8_t responderRandom[kSigmaParamRandomNumberSize]; + uint16_t responderSessionId; + const Crypto::P256PublicKey * pEphPubKey = nullptr; + Platform::ScopedMemoryBuffer msg_R2_Encrypted; + size_t encrypted2Length = 0; + const ReliableMessageProtocolConfig * responderMrpConfig; + }; + + struct EncodeSigma2ResInputs + { + ByteSpan resumptionId; + uint8_t sigma2ResumeMIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + MutableByteSpan resumeMICSpan{ sigma2ResumeMIC }; + uint16_t responderSessionId; + const ReliableMessageProtocolConfig * responderMrpConfig; + }; + /** * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. * diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 1ff82163a50e1c..84d7737c94e761 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -59,7 +59,7 @@ using namespace chip::Crypto; namespace chip { class TestCASESecurePairingDelegate; -class TestCASESession : public Test::LoopbackMessagingContext +class TestCASESession : public Test::LoopbackMessagingContext, public CASESession { public: // Performs shared setup for all tests in the test suite @@ -80,32 +80,6 @@ class TestCASESession : public Test::LoopbackMessagingContext void SimulateUpdateNOCInvalidatePendingEstablishment(); }; -// CASESession Wrapper to Test the protected Functions -class CASESessionWrapper : public CASESession -{ -public: - CHIP_ERROR ParseSigma1Access(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam) - { - return ParseSigma1(tlvReader, outParam); - } - - CHIP_ERROR EncodeSigma1Access(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam) - { - return EncodeSigma1(outMsg, inParam); - } - - CHIP_ERROR EncodeSigma2Access(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam) - - { - return EncodeSigma2(outMsg, inParam); - } - - CHIP_ERROR EncodeSigma2ResumeAccess(System::PacketBufferHandle & outMsg, EncodeSigma2ResInputs & inParam) - { - return EncodeSigma2Resume(outMsg, inParam); - } -}; - void TestCASESession::ServiceEvents() { // Takes a few rounds of this because handling IO messages may schedule work, @@ -771,10 +745,9 @@ static CHIP_ERROR EncodeSigma1Helper(MutableByteSpan & buf) \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - CASESessionWrapper::ParsedSigma1 parsedSigma1; \ - CASESessionWrapper session; \ + ParsedSigma1 parsedSigma1; \ \ - EXPECT_EQ(session.ParseSigma1Access(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ + EXPECT_EQ(ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ if (params::expectSuccess) \ { \ EXPECT_EQ(parsedSigma1.sessionResumptionRequested, \ @@ -896,8 +869,7 @@ TEST_F(TestCASESession, Sigma1ParsingTest) TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg; - CASESessionWrapper session; - CASESessionWrapper::EncodeSigma1Inputs encodeParams; + CASESession::EncodeSigma1Inputs encodeParams; uint8_t random[32]; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], 32), CHIP_NO_ERROR); @@ -910,7 +882,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.initiatorMrpConfig = &MRPConfig; // EncodeSigma1 should fail when there is no public key - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); ASSERT_NE(EphemeralKey, nullptr); @@ -918,39 +890,39 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); // Succeed when Public Key is provided - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); // Free the PacketBuffer msg = nullptr; // EncodeSigma1 should fail when MRP config is missing encodeParams.initiatorMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); // Free the PacketBuffer msg = nullptr; // Succeed when MRP Config is provided encodeParams.initiatorMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma1 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma1Access(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(nonEmptyMsg, encodeParams)); } { System::PacketBufferHandle msg1; System::PacketBufferTLVReader tlvReader; - CASESessionWrapper::ParsedSigma1 parseParams; + CASESession::ParsedSigma1 parseParams; // Round Trip Test: Encode Sigma1, Parse it then verify parsed values - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg1, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg1, encodeParams)); tlvReader.Init(std::move(msg1)); - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1Access(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, ParseSigma1(tlvReader, parseParams)); // compare parsed values with original values EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); @@ -963,7 +935,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) { System::PacketBufferHandle msg2; System::PacketBufferTLVReader tlvReader; - CASESessionWrapper::ParsedSigma1 parseParams; + CASESession::ParsedSigma1 parseParams; // Round Trip Test: Sigma1 with Session Resumption // Encode Sigma1 with Resumption, parse it and and verify with original values @@ -977,12 +949,12 @@ TEST_F(TestCASESession, EncodeSigma1Test) encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MIC); encodeParams.sessionResumptionRequested = true; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma1Access(msg2, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg2, encodeParams)); // Encode and Parse Round Trip Test tlvReader.Init(std::move(msg2)); - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1Access(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, ParseSigma1(tlvReader, parseParams)); // RoundTrip EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); @@ -1002,8 +974,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) TEST_F(TestCASESession, EncodeSigma2Test) { System::PacketBufferHandle msg; - CASESessionWrapper session; - CASESessionWrapper::EncodeSigma2Inputs encodeParams; + CASESession::EncodeSigma2Inputs encodeParams; constexpr uint8_t kEncrypted2datalen = 100U; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); @@ -1023,7 +994,7 @@ TEST_F(TestCASESession, EncodeSigma2Test) ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); // free Buffer owned by PacketBufferHandle msg = nullptr; @@ -1031,42 +1002,42 @@ TEST_F(TestCASESession, EncodeSigma2Test) System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma2 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(nonEmptyMsg, encodeParams)); } // EncodeSigma2 should fail when there is no public key encodeParams.pEphPubKey = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); msg = nullptr; // EncodeSigma2 should fail when TBEData2Encrypted is not allocated encodeParams.msg_R2_Encrypted.Free(); - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); msg = nullptr; // EncodeSigma2 should fail when the encrypted2Length is not set encodeParams.encrypted2Length = 0; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); // Set encrypted2Length again encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; // EncodeSigma2 should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); msg = nullptr; // Succeed when MRP Config is provided encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2Access(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); // Release EphemeralKeyPair gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); @@ -1075,8 +1046,7 @@ TEST_F(TestCASESession, EncodeSigma2Test) TEST_F(TestCASESession, EncodeSigma2ResumeTest) { System::PacketBufferHandle msg; - CASESessionWrapper session; - CASESessionWrapper::EncodeSigma2ResInputs encodeParams; + CASESession::EncodeSigma2ResInputs encodeParams; encodeParams.responderSessionId = 7315; @@ -1084,7 +1054,7 @@ TEST_F(TestCASESession, EncodeSigma2ResumeTest) ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); // Free buffer owned by msg msg = nullptr; @@ -1092,19 +1062,19 @@ TEST_F(TestCASESession, EncodeSigma2ResumeTest) System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma2Resume should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2ResumeAccess(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(nonEmptyMsg, encodeParams)); } - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); msg = nullptr; // EncodeSigma2Resume should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(msg, encodeParams)); // Succeed when MRP Config is provided encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, session.EncodeSigma2ResumeAccess(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); } struct SessionResumptionTestStorage : SessionResumptionStorage From 8e39da6ec0b6bdc54c8c0bc43c6f3819dade86b6 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Mon, 16 Dec 2024 18:52:03 +0100 Subject: [PATCH 09/16] integrating comments --- src/protocols/secure_channel/CASESession.cpp | 51 ++++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index bf10cb78af2538..67d89053a80af0 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -51,17 +51,6 @@ namespace { -enum class Sigma1Tags : uint8_t -{ - kInitiatorRandom = 1, - kInitiatorSessionId = 2, - kDestinationId = 3, - kInitiatorPubKey = 4, - kInitiatorMRPParams = 5, - kResumptionID = 6, - kResume1MIC = 7, -}; - enum class TBEDataTags : uint8_t { kSenderNOC = 1, @@ -78,6 +67,17 @@ enum class TBSDataTags : uint8_t kReceiverPubKey = 4, }; +enum class Sigma1Tags : uint8_t +{ + kInitiatorRandom = 1, + kInitiatorSessionId = 2, + kDestinationId = 3, + kInitiatorPubKey = 4, + kInitiatorMRPParams = 5, + kResumptionID = 6, + kResume1MIC = 7, +}; + enum class Sigma2Tags : uint8_t { kResponderRandom = 1, @@ -89,7 +89,6 @@ enum class Sigma2Tags : uint8_t enum class Sigma2ResTags : uint8_t { - kResumptionID = 1, kSigma2ResumeMIC = 2, kResponderSessionID = 3, @@ -790,7 +789,7 @@ CHIP_ERROR CASESession::SendSigma1() uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; // Struct that will be used as input to EncodeSigma1() method - EncodeSigma1Inputs encodeSigma1Params; + EncodeSigma1Inputs encodeSigma1Inputs; // Lookup fabric info. const auto * fabricInfo = mFabricsTable->FindFabricWithIndex(mFabricIndex); @@ -798,17 +797,17 @@ CHIP_ERROR CASESession::SendSigma1() // Validate that we have a session ID allocated. VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); - encodeSigma1Params.initiatorSessionId = GetLocalSessionId().Value(); + encodeSigma1Inputs.initiatorSessionId = GetLocalSessionId().Value(); // Generate an ephemeral keypair mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); - encodeSigma1Params.pEphPubKey = &mEphemeralKey->Pubkey(); + encodeSigma1Inputs.pEphPubKey = &mEphemeralKey->Pubkey(); // Fill in the random value ReturnErrorOnFailure(DRBG_get_bytes(mInitiatorRandom, sizeof(mInitiatorRandom))); - encodeSigma1Params.initiatorRandom = ByteSpan(mInitiatorRandom); + encodeSigma1Inputs.initiatorRandom = ByteSpan(mInitiatorRandom); // Generate a Destination Identifier based on the node we are attempting to reach { @@ -822,13 +821,13 @@ CHIP_ERROR CASESession::SendSigma1() Credentials::P256PublicKeySpan rootPubKeySpan{ rootPubKey.ConstBytes() }; MutableByteSpan destinationIdSpan(destinationIdentifier); - ReturnErrorOnFailure(GenerateCaseDestinationId(ByteSpan(mIPK), encodeSigma1Params.initiatorRandom, rootPubKeySpan, fabricId, + ReturnErrorOnFailure(GenerateCaseDestinationId(ByteSpan(mIPK), encodeSigma1Inputs.initiatorRandom, rootPubKeySpan, fabricId, mPeerNodeId, destinationIdSpan)); - encodeSigma1Params.destinationId = destinationIdSpan; + encodeSigma1Inputs.destinationId = destinationIdSpan; } VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - encodeSigma1Params.initiatorMrpConfig = &mLocalMRPConfig.Value(); + encodeSigma1Inputs.initiatorMrpConfig = &mLocalMRPConfig.Value(); // Try to find persistent session, and resume it. if (mSessionResumptionStorage != nullptr) @@ -838,18 +837,18 @@ CHIP_ERROR CASESession::SendSigma1() if (err == CHIP_NO_ERROR) { // Found valid resumption state, try to resume the session. - encodeSigma1Params.resumptionId = mResumeResumptionId; - MutableByteSpan resumeMICSpan(encodeSigma1Params.initiatorResume1MIC); - ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Params.initiatorRandom, encodeSigma1Params.resumptionId, + encodeSigma1Inputs.resumptionId = mResumeResumptionId; + MutableByteSpan resumeMICSpan(encodeSigma1Inputs.initiatorResume1MIC); + ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Inputs.initiatorRandom, encodeSigma1Inputs.resumptionId, ByteSpan(kKDFS1RKeyInfo), ByteSpan(kResume1MIC_Nonce), resumeMICSpan)); - encodeSigma1Params.initiatorResumeMICSpan = resumeMICSpan; - encodeSigma1Params.sessionResumptionRequested = true; + encodeSigma1Inputs.initiatorResumeMICSpan = resumeMICSpan; + encodeSigma1Inputs.sessionResumptionRequested = true; } } // Encode Sigma1 in CHIP TLV Format - ReturnErrorOnFailure(EncodeSigma1(msg_R1, encodeSigma1Params)); + ReturnErrorOnFailure(EncodeSigma1(msg_R1, encodeSigma1Inputs)); ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R1->Start(), msg_R1->DataLength() })); @@ -857,7 +856,7 @@ CHIP_ERROR CASESession::SendSigma1() ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma1, std::move(msg_R1), SendFlags(SendMessageFlags::kExpectResponse))); - if (encodeSigma1Params.sessionResumptionRequested) + if (encodeSigma1Inputs.sessionResumptionRequested) { mState = State::kSentSigma1Resume; From 205b27e7463ef7d2bb833fdbe2002650ae28a620 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Tue, 17 Dec 2024 19:51:32 +0100 Subject: [PATCH 10/16] Integrating comments in TestCASESession --- .../secure_channel/tests/TestCASESession.cpp | 262 ++++++++++-------- 1 file changed, 142 insertions(+), 120 deletions(-) diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 84d7737c94e761..f2b4d084fadf26 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -614,24 +614,24 @@ struct Sigma1Params { // Purposefully not using constants like kSigmaParamRandomNumberSize that // the code uses, so we have a cross-check. - static constexpr size_t initiatorRandomLen = 32; - static constexpr uint16_t initiatorSessionId = 0; - static constexpr size_t destinationIdLen = 32; - static constexpr size_t initiatorEphPubKeyLen = 65; - static constexpr size_t resumptionIdLen = 0; // Nonzero means include it. - static constexpr size_t initiatorResumeMICLen = 0; // Nonzero means include it. - - static constexpr uint8_t initiatorRandomTag = 1; - static constexpr uint8_t initiatorSessionIdTag = 2; - static constexpr uint8_t destinationIdTag = 3; - static constexpr uint8_t initiatorEphPubKeyTag = 4; - static constexpr uint8_t resumptionIdTag = 6; - static constexpr uint8_t initiatorResumeMICTag = 7; + static constexpr size_t kInitiatorRandomLen = 32; + static constexpr uint16_t kInitiatorSessionId = 0; + static constexpr size_t kDestinationIdLen = 32; + static constexpr size_t kInitiatorEphPubKeyLen = 65; + static constexpr size_t kResumptionIdLen = 0; // Nonzero means include it. + static constexpr size_t kInitiatorResumeMICLen = 0; // Nonzero means include it. + + static constexpr uint8_t kInitiatorRandomTag = 1; + static constexpr uint8_t kInitiatorSessionIdTag = 2; + static constexpr uint8_t kDestinationIdTag = 3; + static constexpr uint8_t kInitiatorEphPubKeyTag = 4; + static constexpr uint8_t kResumptionIdTag = 6; + static constexpr uint8_t kInitiatorResumeMICTag = 7; static constexpr TLV::Tag NumToTag(uint8_t num) { return TLV::ContextTag(num); } - static constexpr bool includeStructEnd = true; + static constexpr bool kIncludeStructEnd = true; - static constexpr bool expectSuccess = true; + static constexpr bool kExpectSuccess = true; }; TEST_F(TestCASESession, DestinationIdTest) @@ -649,10 +649,10 @@ TEST_F(TestCASESession, DestinationIdTest) 0x9b, 0xc6, 0x1c, 0xd9, 0xc6, 0x2a, 0x2d, 0xf6, 0xd6, 0x4d, 0xfc, 0xaa, 0x9d, 0xc4, 0x72, 0xd4 }; - const uint8_t kInitiatorRandomFromSpec[Sigma1Params::initiatorRandomLen] = { 0x7e, 0x17, 0x12, 0x31, 0x56, 0x8d, 0xfa, 0x17, - 0x20, 0x6b, 0x3a, 0xcc, 0xf8, 0xfa, 0xec, 0x2f, - 0x4d, 0x21, 0xb5, 0x80, 0x11, 0x31, 0x96, 0xf4, - 0x7c, 0x7c, 0x4d, 0xeb, 0x81, 0x0a, 0x73, 0xdc }; + const uint8_t kInitiatorRandomFromSpec[Sigma1Params::kInitiatorRandomLen] = { 0x7e, 0x17, 0x12, 0x31, 0x56, 0x8d, 0xfa, 0x17, + 0x20, 0x6b, 0x3a, 0xcc, 0xf8, 0xfa, 0xec, 0x2f, + 0x4d, 0x21, 0xb5, 0x80, 0x11, 0x31, 0x96, 0xf4, + 0x7c, 0x7c, 0x4d, 0xeb, 0x81, 0x0a, 0x73, 0xdc }; const uint8_t kExpectedDestinationIdFromSpec[Crypto::kSHA256_Hash_Length] = { 0xdc, 0x35, 0xdd, 0x5f, 0xc9, 0x13, 0x4c, 0xc5, 0x54, 0x45, 0x38, 0xc9, 0xc3, 0xfc, 0x42, 0x97, @@ -695,39 +695,37 @@ static CHIP_ERROR EncodeSigma1Helper(MutableByteSpan & buf) TLVType containerType; ReturnErrorOnFailure(writer.StartContainer(AnonymousTag(), kTLVType_Structure, containerType)); - uint8_t initiatorRandom[Params::initiatorRandomLen] = { 1 }; - ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::initiatorRandomTag), ByteSpan(initiatorRandom))); + uint8_t initiatorRandom[Params::kInitiatorRandomLen] = { 1 }; + ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::kInitiatorRandomTag), ByteSpan(initiatorRandom))); - ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::initiatorSessionIdTag), Params::initiatorSessionId)); + ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::kInitiatorSessionIdTag), Params::kInitiatorSessionId)); - uint8_t destinationId[Params::destinationIdLen] = { 2 }; - ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::destinationIdTag), ByteSpan(destinationId))); + uint8_t destinationId[Params::kDestinationIdLen] = { 2 }; + ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::kDestinationIdTag), ByteSpan(destinationId))); - uint8_t initiatorEphPubKey[Params::initiatorEphPubKeyLen] = { 3 }; - ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::initiatorEphPubKeyTag), ByteSpan(initiatorEphPubKey))); + uint8_t initiatorEphPubKey[Params::kInitiatorEphPubKeyLen] = { 3 }; + ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::kInitiatorEphPubKeyTag), ByteSpan(initiatorEphPubKey))); - // I wish we had "if constexpr" support here, so the compiler would know - // resumptionIdLen is nonzero inside the block.... - if constexpr (Params::resumptionIdLen != 0) + if constexpr (Params::kResumptionIdLen != 0) { - uint8_t resumptionId[Params::resumptionIdLen]; + uint8_t resumptionId[Params::kResumptionIdLen]; // to fix _FORTIFY_SOURCE issue, _FORTIFY_SOURCE=2 by default on Android - (&memset)(resumptionId, 4, Params::resumptionIdLen); + (&memset)(resumptionId, 4, Params::kResumptionIdLen); ReturnErrorOnFailure( - writer.Put(Params::NumToTag(Params::resumptionIdTag), ByteSpan(resumptionId, Params::resumptionIdLen))); + writer.Put(Params::NumToTag(Params::kResumptionIdTag), ByteSpan(resumptionId, Params::kResumptionIdLen))); } - if constexpr (Params::initiatorResumeMICLen != 0) + if constexpr (Params::kInitiatorResumeMICLen != 0) { - uint8_t initiatorResumeMIC[Params::initiatorResumeMICLen]; + uint8_t initiatorResumeMIC[Params::kInitiatorResumeMICLen]; // to fix _FORTIFY_SOURCE issue, _FORTIFY_SOURCE=2 by default on Android - (&memset)(initiatorResumeMIC, 5, Params::initiatorResumeMICLen); - ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::initiatorResumeMICTag), - ByteSpan(initiatorResumeMIC, Params::initiatorResumeMICLen))); + (&memset)(initiatorResumeMIC, 5, Params::kInitiatorResumeMICLen); + ReturnErrorOnFailure(writer.Put(Params::NumToTag(Params::kInitiatorResumeMICTag), + ByteSpan(initiatorResumeMIC, Params::kInitiatorResumeMICLen))); } - if constexpr (Params::includeStructEnd) + if constexpr (Params::kIncludeStructEnd) { ReturnErrorOnFailure(writer.EndContainer(containerType)); } @@ -747,23 +745,23 @@ static CHIP_ERROR EncodeSigma1Helper(MutableByteSpan & buf) reader.Init(buf); \ ParsedSigma1 parsedSigma1; \ \ - EXPECT_EQ(ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::expectSuccess); \ - if (params::expectSuccess) \ + EXPECT_EQ(ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::kExpectSuccess); \ + if (params::kExpectSuccess) \ { \ EXPECT_EQ(parsedSigma1.sessionResumptionRequested, \ - params::resumptionIdLen != 0 && params::initiatorResumeMICLen != 0); \ + params::kResumptionIdLen != 0 && params::kInitiatorResumeMICLen != 0); \ /* Add other verification tests here as desired */ \ } \ } while (0) struct BadSigma1ParamsBase : public Sigma1Params { - static constexpr bool expectSuccess = false; + static constexpr bool kExpectSuccess = false; }; struct Sigma1NoStructEnd : public BadSigma1ParamsBase { - static constexpr bool includeStructEnd = false; + static constexpr bool kIncludeStructEnd = false; }; struct Sigma1WrongTags : public BadSigma1ParamsBase @@ -773,72 +771,72 @@ struct Sigma1WrongTags : public BadSigma1ParamsBase struct Sigma1TooLongRandom : public BadSigma1ParamsBase { - static constexpr size_t initiatorRandomLen = 33; + static constexpr size_t kInitiatorRandomLen = 33; }; struct Sigma1TooShortRandom : public BadSigma1ParamsBase { - static constexpr size_t initiatorRandomLen = 31; + static constexpr size_t kInitiatorRandomLen = 31; }; struct Sigma1TooLongDest : public BadSigma1ParamsBase { - static constexpr size_t destinationIdLen = 33; + static constexpr size_t kDestinationIdLen = 33; }; struct Sigma1TooShortDest : public BadSigma1ParamsBase { - static constexpr size_t destinationIdLen = 31; + static constexpr size_t kDestinationIdLen = 31; }; struct Sigma1TooLongPubkey : public BadSigma1ParamsBase { - static constexpr size_t initiatorEphPubKeyLen = 66; + static constexpr size_t kInitiatorEphPubKeyLen = 66; }; struct Sigma1TooShortPubkey : public BadSigma1ParamsBase { - static constexpr size_t initiatorEphPubKeyLen = 64; + static constexpr size_t kInitiatorEphPubKeyLen = 64; }; struct Sigma1WithResumption : public Sigma1Params { - static constexpr size_t resumptionIdLen = 16; - static constexpr size_t initiatorResumeMICLen = 16; + static constexpr size_t kResumptionIdLen = 16; + static constexpr size_t kInitiatorResumeMICLen = 16; }; struct Sigma1TooLongResumptionId : public Sigma1WithResumption { - static constexpr size_t resumptionIdLen = 17; - static constexpr bool expectSuccess = false; + static constexpr size_t kResumptionIdLen = 17; + static constexpr bool kExpectSuccess = false; }; struct Sigma1TooShortResumptionId : public BadSigma1ParamsBase { - static constexpr size_t resumptionIdLen = 15; - static constexpr bool expectSuccess = false; + static constexpr size_t kResumptionIdLen = 15; + static constexpr bool kExpectSuccess = false; }; struct Sigma1TooLongResumeMIC : public Sigma1WithResumption { - static constexpr size_t resumptionIdLen = 17; - static constexpr bool expectSuccess = false; + static constexpr size_t kResumptionIdLen = 17; + static constexpr bool kExpectSuccess = false; }; struct Sigma1TooShortResumeMIC : public Sigma1WithResumption { - static constexpr size_t initiatorResumeMICLen = 15; - static constexpr bool expectSuccess = false; + static constexpr size_t kInitiatorResumeMICLen = 15; + static constexpr bool kExpectSuccess = false; }; struct Sigma1SessionIdMax : public Sigma1Params { - static constexpr uint32_t initiatorSessionId = UINT16_MAX; + static constexpr uint32_t kInitiatorSessionId = UINT16_MAX; }; struct Sigma1SessionIdTooBig : public BadSigma1ParamsBase { - static constexpr uint32_t initiatorSessionId = UINT16_MAX + 1; + static constexpr uint32_t kInitiatorSessionId = UINT16_MAX + 1; }; TEST_F(TestCASESession, Sigma1ParsingTest) @@ -868,7 +866,6 @@ TEST_F(TestCASESession, Sigma1ParsingTest) TEST_F(TestCASESession, EncodeSigma1Test) { - System::PacketBufferHandle msg; CASESession::EncodeSigma1Inputs encodeParams; uint8_t random[32]; @@ -881,30 +878,36 @@ TEST_F(TestCASESession, EncodeSigma1Test) ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.initiatorMrpConfig = &MRPConfig; - // EncodeSigma1 should fail when there is no public key - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // EncodeSigma1 should fail when there is no public key + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + } Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); ASSERT_NE(EphemeralKey, nullptr); EXPECT_EQ(CHIP_NO_ERROR, EphemeralKey->Initialize(ECPKeyTarget::ECDH)); encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); - // Succeed when Public Key is provided - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); - - // Free the PacketBuffer - msg = nullptr; - - // EncodeSigma1 should fail when MRP config is missing - encodeParams.initiatorMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // EncodeSigma1 will Succeed when Public Key is provided + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); + } - // Free the PacketBuffer - msg = nullptr; + { + System::PacketBufferHandle msg; + // EncodeSigma1 should fail when MRP config is missing + encodeParams.initiatorMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + } - // Succeed when MRP Config is provided - encodeParams.initiatorMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // Succeed when MRP Config is provided + encodeParams.initiatorMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); + } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); @@ -973,7 +976,6 @@ TEST_F(TestCASESession, EncodeSigma1Test) TEST_F(TestCASESession, EncodeSigma2Test) { - System::PacketBufferHandle msg; CASESession::EncodeSigma2Inputs encodeParams; constexpr uint8_t kEncrypted2datalen = 100U; @@ -988,15 +990,16 @@ TEST_F(TestCASESession, EncodeSigma2Test) // TBEData2Encrypted encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; - encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); + encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); // responder Session Parameters ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); - // free Buffer owned by PacketBufferHandle - msg = nullptr; + { + System::PacketBufferHandle msg; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); @@ -1005,47 +1008,62 @@ TEST_F(TestCASESession, EncodeSigma2Test) EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(nonEmptyMsg, encodeParams)); } - // EncodeSigma2 should fail when there is no public key - encodeParams.pEphPubKey = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); - - encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); - msg = nullptr; + { + System::PacketBufferHandle msg; - // EncodeSigma2 should fail when TBEData2Encrypted is not allocated - encodeParams.msg_R2_Encrypted.Free(); + // EncodeSigma2 should fail when there is no public key + encodeParams.pEphPubKey = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + } - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); - encodeParams.msg_R2_Encrypted.Alloc(encodeParams.encrypted2Length); + { + System::PacketBufferHandle msg; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + } - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); - msg = nullptr; + { + System::PacketBufferHandle msg; + // EncodeSigma2 should fail when TBEData2Encrypted is not allocated + encodeParams.msgR2Encrypted.Free(); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + } - // EncodeSigma2 should fail when the encrypted2Length is not set - encodeParams.encrypted2Length = 0; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); + { + System::PacketBufferHandle msg; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + } + { + System::PacketBufferHandle msg; + // EncodeSigma2 should fail when the encrypted2Length is not set + encodeParams.encrypted2Length = 0; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + } // Set encrypted2Length again encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; - // EncodeSigma2 should fail when MRP config is missing - encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); - msg = nullptr; - - // Succeed when MRP Config is provided - encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // EncodeSigma2 should fail when MRP config is missing + encodeParams.responderMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + } + { + System::PacketBufferHandle msg; + // Succeed when MRP Config is provided + encodeParams.responderMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + } // Release EphemeralKeyPair gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); } TEST_F(TestCASESession, EncodeSigma2ResumeTest) { - System::PacketBufferHandle msg; CASESession::EncodeSigma2ResInputs encodeParams; encodeParams.responderSessionId = 7315; @@ -1054,9 +1072,10 @@ TEST_F(TestCASESession, EncodeSigma2ResumeTest) ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); - // Free buffer owned by msg - msg = nullptr; + { + System::PacketBufferHandle msg; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); + } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); @@ -1065,16 +1084,19 @@ TEST_F(TestCASESession, EncodeSigma2ResumeTest) EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(nonEmptyMsg, encodeParams)); } - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); - msg = nullptr; - - // EncodeSigma2Resume should fail when MRP config is missing - encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // EncodeSigma2Resume should fail when MRP config is missing + encodeParams.responderMrpConfig = nullptr; + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(msg, encodeParams)); + } - // Succeed when MRP Config is provided - encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); + { + System::PacketBufferHandle msg; + // Succeed when MRP Config is provided + encodeParams.responderMrpConfig = &MRPConfig; + EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); + } } struct SessionResumptionTestStorage : SessionResumptionStorage From 72e85cccbbaac3a6b234c18f660ba62cbf9bcb3f Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Tue, 17 Dec 2024 19:52:57 +0100 Subject: [PATCH 11/16] integrate comments on CASESession --- src/protocols/secure_channel/CASESession.cpp | 386 +++++++++---------- src/protocols/secure_channel/CASESession.h | 6 +- 2 files changed, 190 insertions(+), 202 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 67d89053a80af0..53c443ecdbf503 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -102,9 +102,9 @@ enum class Sigma3Tags : uint8_t // Utility to extract the underlying value of TLV Tag enum classes, used in TLV encoding and parsing. template -constexpr auto ToRaw(Enum e) +constexpr chip::TLV::Tag AsTlvContextTag(Enum e) { - return static_cast>(e); + return chip::TLV::ContextTag(static_cast>(e)); } } // namespace @@ -117,6 +117,7 @@ using namespace Messaging; using namespace Encoding; using namespace Protocols::SecureChannel; using namespace Tracing; +using namespace TLV; constexpr uint8_t kKDFSR2Info[] = { 0x53, 0x69, 0x67, 0x6d, 0x61, 0x32 }; constexpr uint8_t kKDFSR3Info[] = { 0x53, 0x69, 0x67, 0x6d, 0x61, 0x33 }; @@ -785,7 +786,7 @@ CHIP_ERROR CASESession::SendSigma1() { MATTER_TRACE_SCOPE("SendSigma1", "CASESession"); - System::PacketBufferHandle msg_R1; + System::PacketBufferHandle msgR1; uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; // Struct that will be used as input to EncodeSigma1() method @@ -848,12 +849,12 @@ CHIP_ERROR CASESession::SendSigma1() } // Encode Sigma1 in CHIP TLV Format - ReturnErrorOnFailure(EncodeSigma1(msg_R1, encodeSigma1Inputs)); + ReturnErrorOnFailure(EncodeSigma1(msgR1, encodeSigma1Inputs)); - ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R1->Start(), msg_R1->DataLength() })); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msgR1->Start(), msgR1->DataLength() })); // Call delegate to send the msg to peer - ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma1, std::move(msg_R1), + ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma1, std::move(msgR1), SendFlags(SendMessageFlags::kExpectResponse))); if (encodeSigma1Inputs.sessionResumptionRequested) @@ -882,45 +883,44 @@ CHIP_ERROR CASESession::SendSigma1() CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSigma1Inputs & input) { - MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); - 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, // resumptionId - CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES // initiatorResumeMIC - ); - // the PacketBufferHandler should be empty VerifyOrReturnError(msg.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); - msg = System::PacketBufferHandle::New(data_len); + size_t dataLen = EstimateStructOverhead(kSigmaParamRandomNumberSize, // initiatorRandom + sizeof(uint16_t), // initiatorSessionId, + kSHA256_Hash_Length, // destinationId + kP256_PublicKey_Length, // InitiatorEphPubKey, + SessionParameters::kEstimatedTLVSize, // initiatorSessionParams + SessionResumptionStorage::kResumptionIdSize, // resumptionId + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES // initiatorResumeMIC + ); + + msg = System::PacketBufferHandle::New(dataLen); VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriter; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + TLVType outerContainerType = kTLVType_NotSpecified; tlvWriter.Init(std::move(msg)); - ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorRandom)), input.initiatorRandom)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorSessionId)), input.initiatorSessionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kDestinationId)), input.destinationId)); + ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kInitiatorRandom), input.initiatorRandom)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kInitiatorSessionId), input.initiatorSessionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kDestinationId), input.destinationId)); - VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorPubKey)), *input.pEphPubKey, + ReturnErrorOnFailure(tlvWriter.PutBytes(AsTlvContextTag(Sigma1Tags::kInitiatorPubKey), *input.pEphPubKey, static_cast(input.pEphPubKey->Length()))); VerifyOrReturnError(input.initiatorMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure( - EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams)), *input.initiatorMrpConfig, tlvWriter)); + EncodeSessionParameters(AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams), *input.initiatorMrpConfig, tlvWriter)); if (input.sessionResumptionRequested) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kResumptionID)), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma1Tags::kResume1MIC)), input.initiatorResumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kResumptionID), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kResume1MIC), input.initiatorResumeMICSpan)); } ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); @@ -942,29 +942,28 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & { case Step::kSendSigma2: { - System::PacketBufferHandle msg_R2; + System::PacketBufferHandle msgR2; EncodeSigma2Inputs encodeSigma2; - // TODO verify MATTER_LOG_METRIC locations MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); SuccessOrExit(err = PrepareSigma2(encodeSigma2)); - SuccessOrExit(err = EncodeSigma2(msg_R2, encodeSigma2)); - SuccessOrExitAction(err = SendSigma2(msg_R2), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2, err)); + SuccessOrExit(err = EncodeSigma2(msgR2, encodeSigma2)); + SuccessOrExitAction(err = SendSigma2(std::move(msgR2)), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2, err)); mDelegate->OnSessionEstablishmentStarted(); break; } case Step::kSendSigma2Resume: { - System::PacketBufferHandle msg_R2_resume; + System::PacketBufferHandle msgR2Resume; EncodeSigma2ResInputs encodeSigma2Resume; MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); SuccessOrExit(err = PrepareSigma2Resume(encodeSigma2Resume)); - SuccessOrExit(err = EncodeSigma2Resume(msg_R2_resume, encodeSigma2Resume)); - SuccessOrExitAction(err = SendSigma2Resume(msg_R2_resume), + SuccessOrExit(err = EncodeSigma2Resume(msgR2Resume, encodeSigma2Resume)); + SuccessOrExitAction(err = SendSigma2Resume(std::move(msgR2Resume)), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2Resume, err)); mDelegate->OnSessionEstablishmentStarted(); @@ -1077,23 +1076,23 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) ChipLogProgress(SecureChannel, "Received Sigma1 msg"); MATTER_TRACE_COUNTER("Sigma1"); + VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBufferTLVReader tlvReader; + tlvReader.Init(std::move(msg)); // Struct that will serve as output in ParseSigma1 ParsedSigma1 parsedSigma1; - ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); - - tlvReader.Init(std::move(msg)); - ReturnErrorOnFailure(ParseSigma1(tlvReader, parsedSigma1)); ChipLogDetail(SecureChannel, "Peer assigned session key ID %d", parsedSigma1.initiatorSessionId); SetPeerSessionId(parsedSigma1.initiatorSessionId); - VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); - // Set the MRP parameters provided in the Sigma1 message if (parsedSigma1.initiatorMrpParamsPresent) { @@ -1149,72 +1148,70 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResInputs & output) +CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResInputs & outSigma2ResData) { MATTER_TRACE_SCOPE("PrepareSigma2Resume", "CASESession"); + VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + // Validate that we have a session ID allocated. VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); - output.responderSessionId = GetLocalSessionId().Value(); + outSigma2ResData.responderSessionId = GetLocalSessionId().Value(); // Generate a new resumption ID ReturnErrorOnFailure(DRBG_get_bytes(mNewResumptionId.data(), mNewResumptionId.size())); - output.resumptionId = mNewResumptionId; + outSigma2ResData.resumptionId = mNewResumptionId; ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), mNewResumptionId, ByteSpan(kKDFS2RKeyInfo), - ByteSpan(kResume2MIC_Nonce), output.resumeMICSpan)); - - VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - output.responderMrpConfig = &mLocalMRPConfig.Value(); + ByteSpan(kResume2MIC_Nonce), outSigma2ResData.resumeMICSpan)); - mState = State::kSentSigma2Resume; + outSigma2ResData.responderMrpConfig = &mLocalMRPConfig.Value(); return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msg_R2_resume, EncodeSigma2ResInputs & input) +CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Resume, EncodeSigma2ResInputs & input) { MATTER_TRACE_SCOPE("EncodeSigma2Resume", "CASESession"); - size_t max_sigma2_resume_data_len = TLV::EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID - CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, // sigma2ResumeMIC - sizeof(uint16_t), // responderSessionID - SessionParameters::kEstimatedTLVSize // responderSessionParams - ); // the passed PacketBufferHandler should be empty - VerifyOrReturnError(msg_R2_resume.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(msgR2Resume.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + + size_t maxDatalLen = EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, // sigma2ResumeMIC + sizeof(uint16_t), // responderSessionID + SessionParameters::kEstimatedTLVSize // responderSessionParams + ); - msg_R2_resume = System::PacketBufferHandle::New(max_sigma2_resume_data_len); - VerifyOrReturnError(!msg_R2_resume.IsNull(), CHIP_ERROR_NO_MEMORY); + msgR2Resume = System::PacketBufferHandle::New(maxDatalLen); + VerifyOrReturnError(!msgR2Resume.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriter; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriter.Init(std::move(msg_R2_resume)); - - ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kResumptionID)), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kSigma2ResumeMIC)), input.resumeMICSpan)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(Sigma2ResTags::kResponderSessionID)), input.responderSessionId)); + tlvWriter.Init(std::move(msgR2Resume)); - VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kResumptionID), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kSigma2ResumeMIC), input.resumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kResponderSessionID), input.responderSessionId)); ReturnErrorOnFailure( - EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma2ResTags::kResponderMRPParams)), *input.responderMrpConfig, tlvWriter)); + EncodeSessionParameters(AsTlvContextTag(Sigma2ResTags::kResponderMRPParams), *input.responderMrpConfig, tlvWriter)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Finalize(&msg_R2_resume)); + ReturnErrorOnFailure(tlvWriter.Finalize(&msgR2Resume)); return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume) +CHIP_ERROR CASESession::SendSigma2Resume(System::PacketBufferHandle && msgR2Resume) { // Call delegate to send the msg to peer ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma2Resume, - std::move(msg_R2_resume), - SendFlags(SendMessageFlags::kExpectResponse))); + std::move(msgR2Resume), SendFlags(SendMessageFlags::kExpectResponse))); mState = State::kSentSigma2Resume; @@ -1223,14 +1220,15 @@ CHIP_ERROR CASESession::SendSigma2Resume(System::PacketBufferHandle & msg_R2_res return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) +CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & outSigma2Data) { - MATTER_TRACE_SCOPE("PrepareSigma2", "CASESession"); - VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); - output.responderSessionId = GetLocalSessionId().Value(); + MATTER_TRACE_SCOPE("PrepareSigma2", "CASESession"); VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE); + outSigma2Data.responderSessionId = GetLocalSessionId().Value(); chip::Platform::ScopedMemoryBuffer icacBuf; VerifyOrReturnError(icacBuf.Alloc(kMaxCHIPCertLength), CHIP_ERROR_NO_MEMORY); @@ -1245,63 +1243,64 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) ReturnErrorOnFailure(mFabricsTable->FetchNOCCert(mFabricIndex, nocCert)); // Fill in the random value - ReturnErrorOnFailure(DRBG_get_bytes(&output.responderRandom[0], sizeof(output.responderRandom))); + ReturnErrorOnFailure(DRBG_get_bytes(&outSigma2Data.responderRandom[0], sizeof(outSigma2Data.responderRandom))); // Generate an ephemeral keypair mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); - output.pEphPubKey = &mEphemeralKey->Pubkey(); + outSigma2Data.pEphPubKey = &mEphemeralKey->Pubkey(); // Generate a Shared Secret ReturnErrorOnFailure(mEphemeralKey->ECDH_derive_secret(mRemotePubKey, mSharedSecret)); - uint8_t msg_salt[kIPKSize + kSigmaParamRandomNumberSize + kP256_PublicKey_Length + kSHA256_Hash_Length]; + uint8_t msgSalt[kIPKSize + kSigmaParamRandomNumberSize + kP256_PublicKey_Length + kSHA256_Hash_Length]; - MutableByteSpan saltSpan(msg_salt); - ReturnErrorOnFailure(ConstructSaltSigma2(ByteSpan(output.responderRandom), mEphemeralKey->Pubkey(), ByteSpan(mIPK), saltSpan)); + MutableByteSpan saltSpan(msgSalt); + ReturnErrorOnFailure( + ConstructSaltSigma2(ByteSpan(outSigma2Data.responderRandom), mEphemeralKey->Pubkey(), ByteSpan(mIPK), saltSpan)); AutoReleaseSessionKey sr2k(*mSessionManager->GetSessionKeystore()); ReturnErrorOnFailure(DeriveSigmaKey(saltSpan, ByteSpan(kKDFSR2Info), sr2k)); // Construct Sigma2 TBS Data - size_t msg_r2_signed_len = TLV::EstimateStructOverhead(kMaxCHIPCertLength, // responderNoc - kMaxCHIPCertLength, // responderICAC - kP256_PublicKey_Length, // responderEphPubKey - kP256_PublicKey_Length // InitiatorEphPubKey + size_t msgR2SignedLen = EstimateStructOverhead(kMaxCHIPCertLength, // responderNoc + kMaxCHIPCertLength, // responderICAC + kP256_PublicKey_Length, // responderEphPubKey + kP256_PublicKey_Length // InitiatorEphPubKey ); - chip::Platform::ScopedMemoryBuffer msg_R2_Signed; - VerifyOrReturnError(msg_R2_Signed.Alloc(msg_r2_signed_len), CHIP_ERROR_NO_MEMORY); - - ReturnErrorOnFailure(ConstructTBSData(nocCert, icaCert, ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), - ByteSpan(mRemotePubKey, mRemotePubKey.Length()), msg_R2_Signed.Get(), msg_r2_signed_len)); - - // Generate a Signature P256ECDSASignature tbsData2Signature; - ReturnErrorOnFailure( - mFabricsTable->SignWithOpKeypair(mFabricIndex, ByteSpan{ msg_R2_Signed.Get(), msg_r2_signed_len }, tbsData2Signature)); - msg_R2_Signed.Free(); + { + chip::Platform::ScopedMemoryBuffer msgR2Signed; + VerifyOrReturnError(msgR2Signed.Alloc(msgR2SignedLen), CHIP_ERROR_NO_MEMORY); + + ReturnErrorOnFailure(ConstructTBSData(nocCert, icaCert, ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), + ByteSpan(mRemotePubKey, mRemotePubKey.Length()), msgR2Signed.Get(), msgR2SignedLen)); + // Generate a Signature + ReturnErrorOnFailure( + mFabricsTable->SignWithOpKeypair(mFabricIndex, ByteSpan{ msgR2Signed.Get(), msgR2SignedLen }, tbsData2Signature)); + } // Construct Sigma2 TBE Data - size_t msg_r2_signed_enc_len = TLV::EstimateStructOverhead(nocCert.size(), // responderNoc - icaCert.size(), // responderICAC - tbsData2Signature.Length(), // signature - SessionResumptionStorage::kResumptionIdSize // resumptionID + size_t msgR2SignedEncLen = EstimateStructOverhead(nocCert.size(), // responderNoc + icaCert.size(), // responderICAC + tbsData2Signature.Length(), // signature + SessionResumptionStorage::kResumptionIdSize // resumptionID ); - VerifyOrReturnError(output.msg_R2_Encrypted.Alloc(msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES), + VerifyOrReturnError(outSigma2Data.msgR2Encrypted.Alloc(msgR2SignedEncLen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES), CHIP_ERROR_NO_MEMORY); - TLV::TLVWriter tlvWriter; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + TLVWriter tlvWriter; + TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriter.Init(output.msg_R2_Encrypted.Get(), msg_r2_signed_enc_len); - ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)), nocCert)); + tlvWriter.Init(outSigma2Data.msgR2Encrypted.Get(), msgR2SignedEncLen); + ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kSenderNOC), nocCert)); if (!icaCert.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderICAC)), icaCert)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kSenderICAC), icaCert)); } // We are now done with ICAC and NOC certs so we can release the memory. @@ -1313,86 +1312,82 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & output) nocCert = MutableByteSpan{}; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(TBEDataTags::kSignature)), tbsData2Signature.ConstBytes(), + ReturnErrorOnFailure(tlvWriter.PutBytes(AsTlvContextTag(TBEDataTags::kSignature), tbsData2Signature.ConstBytes(), static_cast(tbsData2Signature.Length()))); // Generate a new resumption ID ReturnErrorOnFailure(DRBG_get_bytes(mNewResumptionId.data(), mNewResumptionId.size())); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kResumptionID)), mNewResumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kResumptionID), mNewResumptionId)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); - msg_r2_signed_enc_len = static_cast(tlvWriter.GetLengthWritten()); - output.encrypted2Length = msg_r2_signed_enc_len + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; + msgR2SignedEncLen = static_cast(tlvWriter.GetLengthWritten()); + outSigma2Data.encrypted2Length = msgR2SignedEncLen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; // Generate the encrypted data blob - ReturnErrorOnFailure(AES_CCM_encrypt(output.msg_R2_Encrypted.Get(), msg_r2_signed_enc_len, nullptr, 0, sr2k.KeyHandle(), - kTBEData2_Nonce, kTBEDataNonceLength, output.msg_R2_Encrypted.Get(), - output.msg_R2_Encrypted.Get() + msg_r2_signed_enc_len, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); + ReturnErrorOnFailure(AES_CCM_encrypt(outSigma2Data.msgR2Encrypted.Get(), msgR2SignedEncLen, nullptr, 0, sr2k.KeyHandle(), + kTBEData2_Nonce, kTBEDataNonceLength, outSigma2Data.msgR2Encrypted.Get(), + outSigma2Data.msgR2Encrypted.Get() + msgR2SignedEncLen, + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); - VerifyOrReturnError(mLocalMRPConfig.HasValue(), CHIP_ERROR_INCORRECT_STATE); - output.responderMrpConfig = &mLocalMRPConfig.Value(); + outSigma2Data.responderMrpConfig = &mLocalMRPConfig.Value(); return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msg_R2, EncodeSigma2Inputs & input) +CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msgR2, EncodeSigma2Inputs & input) { + // the PacketBufferHandler should be empty + VerifyOrReturnError(msgR2.IsNull(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); + // Check if msgR2Encrypted is not nullptr + VerifyOrReturnError(input.msgR2Encrypted, CHIP_ERROR_INCORRECT_STATE); + // Check if length of msgR2Encrypted is set and is at least larger than the MIC length + VerifyOrReturnError(input.encrypted2Length > CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); - size_t data_len = TLV::EstimateStructOverhead(kSigmaParamRandomNumberSize, // responderRandom - sizeof(uint16_t), // responderSessionId - kP256_PublicKey_Length, // responderEphPubKey - input.encrypted2Length, // encrypted2 - SessionParameters::kEstimatedTLVSize // responderSessionParams + size_t dataLen = EstimateStructOverhead(kSigmaParamRandomNumberSize, // responderRandom + sizeof(uint16_t), // responderSessionId + kP256_PublicKey_Length, // responderEphPubKey + input.encrypted2Length, // encrypted2 + SessionParameters::kEstimatedTLVSize // responderSessionParams ); - // the PacketBufferHandler should be empty - VerifyOrReturnError(msg_R2.IsNull(), CHIP_ERROR_INCORRECT_STATE); - - msg_R2 = System::PacketBufferHandle::New(data_len); - VerifyOrReturnError(!msg_R2.IsNull(), CHIP_ERROR_NO_MEMORY); + msgR2 = System::PacketBufferHandle::New(dataLen); + VerifyOrReturnError(!msgR2.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriterMsg2; - TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified; + TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriterMsg2.Init(std::move(msg_R2)); - ReturnErrorOnFailure(tlvWriterMsg2.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); + tlvWriterMsg2.Init(std::move(msgR2)); + ReturnErrorOnFailure(tlvWriterMsg2.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderRandom)), &input.responderRandom[0], + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kResponderRandom), &input.responderRandom[0], sizeof(input.responderRandom))); - ReturnErrorOnFailure(tlvWriterMsg2.Put(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderSessionId)), input.responderSessionId)); - - VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(tlvWriterMsg2.Put(AsTlvContextTag(Sigma2Tags::kResponderSessionId), input.responderSessionId)); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderEphPubKey)), *input.pEphPubKey, + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kResponderEphPubKey), *input.pEphPubKey, static_cast(input.pEphPubKey->Length()))); - // Check if msg_R2_Encrypted is not nullptr - VerifyOrReturnError(input.msg_R2_Encrypted, CHIP_ERROR_INCORRECT_STATE); - - // Check if length of msg_R2_Encrypted is set and is at least larger than the MIC length - VerifyOrReturnError(input.encrypted2Length > CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INCORRECT_STATE); - - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(TLV::ContextTag(ToRaw(Sigma2Tags::kEncrypted2)), input.msg_R2_Encrypted.Get(), + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kEncrypted2), input.msgR2Encrypted.Get(), static_cast(input.encrypted2Length))); - VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure( - EncodeSessionParameters(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderMRPParams)), *input.responderMrpConfig, tlvWriterMsg2)); + EncodeSessionParameters(AsTlvContextTag(Sigma2Tags::kResponderMRPParams), *input.responderMrpConfig, tlvWriterMsg2)); ReturnErrorOnFailure(tlvWriterMsg2.EndContainer(outerContainerType)); - ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msg_R2)); + ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msgR2)); return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::SendSigma2(System::PacketBufferHandle & msg_R2) +CHIP_ERROR CASESession::SendSigma2(System::PacketBufferHandle && msgR2) { MATTER_TRACE_SCOPE("SendSigma2", "CASESession"); - ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg_R2->Start(), msg_R2->DataLength() })); + ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msgR2->Start(), msgR2->DataLength() })); // Call delegate to send the msg to peer - ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma2, std::move(msg_R2), + ReturnErrorOnFailure(mExchangeCtxt.Value()->SendMessage(Protocols::SecureChannel::MsgType::CASE_Sigma2, std::move(msgR2), SendFlags(SendMessageFlags::kExpectResponse))); mState = State::kSentSigma2; @@ -1542,18 +1537,18 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = tlvReader.EnterContainer(containerType)); // Retrieve Responder's Random value - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderRandom)))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(Sigma2Tags::kResponderRandom))); SuccessOrExit(err = tlvReader.GetBytes(responderRandom, sizeof(responderRandom))); // Assign Session ID - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_UnsignedInteger, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderSessionId)))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_UnsignedInteger, AsTlvContextTag(Sigma2Tags::kResponderSessionId))); SuccessOrExit(err = tlvReader.Get(responderSessionId)); ChipLogDetail(SecureChannel, "Peer assigned session session ID %d", responderSessionId); SetPeerSessionId(responderSessionId); // Retrieve Responder's Ephemeral Pubkey - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kResponderEphPubKey)))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(Sigma2Tags::kResponderEphPubKey))); SuccessOrExit(err = tlvReader.GetBytes(mRemotePubKey, static_cast(mRemotePubKey.Length()))); // Generate a Shared Secret @@ -1569,7 +1564,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ buf, buflen })); // Generate decrypted data - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma2Tags::kEncrypted2)))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(Sigma2Tags::kEncrypted2))); max_msg_r2_signed_enc_len = TLV::EstimateStructOverhead(Credentials::kMaxCHIPCertLength, Credentials::kMaxCHIPCertLength, tbsData2Signature.Length(), @@ -1593,15 +1588,15 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = decryptedDataTlvReader.Next(containerType, TLV::AnonymousTag())); SuccessOrExit(err = decryptedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBEDataTags::kSenderNOC))); SuccessOrExit(err = decryptedDataTlvReader.Get(responderNOC)); SuccessOrExit(err = decryptedDataTlvReader.Next()); - if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSenderICAC)) + if (decryptedDataTlvReader.GetTag() == AsTlvContextTag(TBEDataTags::kSenderICAC)) { VerifyOrExit(decryptedDataTlvReader.GetType() == TLV::kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); SuccessOrExit(err = decryptedDataTlvReader.Get(responderICAC)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSignature)))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBEDataTags::kSignature))); } // Validate responder identity located in msg_r2_encrypted @@ -1628,8 +1623,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), msg_R2_Signed.Get(), msg_r2_signed_len)); - VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSignature), - err = CHIP_ERROR_INVALID_TLV_TAG); + VerifyOrExit(decryptedDataTlvReader.GetTag() == AsTlvContextTag(TBEDataTags::kSignature), err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(tbsData2Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); tbsData2Signature.SetLength(decryptedDataTlvReader.GetLength()); SuccessOrExit(err = decryptedDataTlvReader.GetBytes(tbsData2Signature.Bytes(), tbsData2Signature.Length())); @@ -1638,7 +1632,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) SuccessOrExit(err = responderPublicKey.ECDSA_validate_msg_signature(msg_R2_Signed.Get(), msg_r2_signed_len, tbsData2Signature)); // Retrieve session resumption ID - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kResumptionID)))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBEDataTags::kResumptionID))); SuccessOrExit(err = decryptedDataTlvReader.GetBytes(mNewResumptionId.data(), mNewResumptionId.size())); // Retrieve peer CASE Authenticated Tags (CATs) from peer's NOC. @@ -1647,7 +1641,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) // Retrieve responderMRPParams if present if (tlvReader.Next() != CHIP_END_OF_TLV) { - SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(ToRaw(Sigma2Tags::kResponderMRPParams)), tlvReader)); + SuccessOrExit(err = DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma2Tags::kResponderMRPParams), tlvReader)); mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( GetRemoteSessionParameters()); } @@ -1766,10 +1760,10 @@ CHIP_ERROR CASESession::SendSigma3b(SendSigma3Data & data, bool & cancel) tlvWriter.Init(data.msg_R3_Encrypted.Get(), data.msg_r3_encrypted_len); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)), data.nocCert)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kSenderNOC), data.nocCert)); if (!data.icaCert.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBEDataTags::kSenderICAC)), data.icaCert)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kSenderICAC), data.icaCert)); } // We are now done with ICAC and NOC certs so we can release the memory. @@ -1781,8 +1775,7 @@ CHIP_ERROR CASESession::SendSigma3b(SendSigma3Data & data, bool & cancel) data.nocCert = MutableByteSpan{}; } - ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(ToRaw(TBEDataTags::kSignature)), - data.tbsData3Signature.ConstBytes(), + ReturnErrorOnFailure(tlvWriter.PutBytes(AsTlvContextTag(TBEDataTags::kSignature), data.tbsData3Signature.ConstBytes(), static_cast(data.tbsData3Signature.Length()))); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); @@ -1923,7 +1916,7 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) max_msg_r3_signed_enc_len = TLV::EstimateStructOverhead(Credentials::kMaxCHIPCertLength, Credentials::kMaxCHIPCertLength, data.tbsData3Signature.Length(), kCaseOverheadForFutureTbeData); - SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(Sigma3Tags::kEncrypted3)))); + SuccessOrExit(err = tlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(Sigma3Tags::kEncrypted3))); msg_r3_encrypted_len_with_tag = tlvReader.GetLength(); @@ -1954,16 +1947,15 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) SuccessOrExit(err = decryptedDataTlvReader.Next(containerType, TLV::AnonymousTag())); SuccessOrExit(err = decryptedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSenderNOC)))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBEDataTags::kSenderNOC))); SuccessOrExit(err = decryptedDataTlvReader.Get(data.initiatorNOC)); SuccessOrExit(err = decryptedDataTlvReader.Next()); - if (TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSenderICAC)) + if (decryptedDataTlvReader.GetTag() == AsTlvContextTag(TBEDataTags::kSenderICAC)) { VerifyOrExit(decryptedDataTlvReader.GetType() == TLV::kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE); SuccessOrExit(err = decryptedDataTlvReader.Get(data.initiatorICAC)); - SuccessOrExit( - err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBEDataTags::kSignature)))); + SuccessOrExit(err = decryptedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBEDataTags::kSignature))); } // Step 4 - Construct Sigma3 TBS Data @@ -1976,8 +1968,7 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) ByteSpan(mEphemeralKey->Pubkey(), mEphemeralKey->Pubkey().Length()), data.msg_R3_Signed.Get(), data.msg_r3_signed_len)); - VerifyOrExit(TLV::TagNumFromTag(decryptedDataTlvReader.GetTag()) == ToRaw(TBEDataTags::kSignature), - err = CHIP_ERROR_INVALID_TLV_TAG); + VerifyOrExit(decryptedDataTlvReader.GetTag() == AsTlvContextTag(TBEDataTags::kSignature), err = CHIP_ERROR_INVALID_TLV_TAG); VerifyOrExit(data.tbsData3Signature.Capacity() >= decryptedDataTlvReader.GetLength(), err = CHIP_ERROR_INVALID_TLV_ELEMENT); data.tbsData3Signature.SetLength(decryptedDataTlvReader.GetLength()); SuccessOrExit(err = decryptedDataTlvReader.GetBytes(data.tbsData3Signature.Bytes(), data.tbsData3Signature.Length())); @@ -2003,14 +1994,12 @@ CHIP_ERROR CASESession::HandleSigma3a(System::PacketBufferHandle && msg) SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())); SuccessOrExit(err = signedDataTlvReader.EnterContainer(containerType)); - SuccessOrExit(err = - signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBSDataTags::kSenderNOC)))); + SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBSDataTags::kSenderNOC))); SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorNOC)); if (!data.initiatorICAC.empty()) { - SuccessOrExit( - err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, TLV::ContextTag(ToRaw(TBSDataTags::kSenderICAC)))); + SuccessOrExit(err = signedDataTlvReader.Next(TLV::kTLVType_ByteString, AsTlvContextTag(TBSDataTags::kSenderICAC))); SuccessOrExit(err = signedDataTlvReader.Get(data.initiatorICAC)); } } @@ -2201,13 +2190,13 @@ CHIP_ERROR CASESession::ConstructTBSData(const ByteSpan & senderNOC, const ByteS tlvWriter.Init(tbsData, tbsDataLen); ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderNOC)), senderNOC)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBSDataTags::kSenderNOC), senderNOC)); if (!senderICAC.empty()) { - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderICAC)), senderICAC)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBSDataTags::kSenderICAC), senderICAC)); } - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kSenderPubKey)), senderPubKey)); - ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(ToRaw(TBSDataTags::kReceiverPubKey)), receiverPubKey)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBSDataTags::kSenderPubKey), senderPubKey)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBSDataTags::kReceiverPubKey), receiverPubKey)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize()); tbsDataLen = static_cast(tlvWriter.GetLengthWritten()); @@ -2312,35 +2301,34 @@ CHIP_ERROR CASESession::OnFailureStatusReport(Protocols::SecureChannel::GeneralS return err; } -CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & output) +CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParsedSigma1) { - using namespace TLV; TLVType containerType = kTLVType_Structure; ReturnErrorOnFailure(tlvReader.Next(containerType, AnonymousTag())); ReturnErrorOnFailure(tlvReader.EnterContainer(containerType)); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorRandom)))); - ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorRandom)); - VerifyOrReturnError(output.initiatorRandom.size() == kSigmaParamRandomNumberSize, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kInitiatorRandom))); + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorRandom)); + VerifyOrReturnError(outParsedSigma1.initiatorRandom.size() == kSigmaParamRandomNumberSize, CHIP_ERROR_INVALID_CASE_PARAMETER); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorSessionId)))); - ReturnErrorOnFailure(tlvReader.Get(output.initiatorSessionId)); + ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kInitiatorSessionId))); + ReturnErrorOnFailure(tlvReader.Get(outParsedSigma1.initiatorSessionId)); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kDestinationId)))); - ReturnErrorOnFailure(tlvReader.GetByteView(output.destinationId)); - VerifyOrReturnError(output.destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kDestinationId))); + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.destinationId)); + VerifyOrReturnError(outParsedSigma1.destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); - ReturnErrorOnFailure(tlvReader.Next(ContextTag(ToRaw(Sigma1Tags::kInitiatorPubKey)))); - ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorEphPubKey)); - VerifyOrReturnError(output.initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); + ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kInitiatorPubKey))); + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorEphPubKey)); + VerifyOrReturnError(outParsedSigma1.initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); // Optional members start here. CHIP_ERROR err = tlvReader.Next(); - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams))) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams)) { - ReturnErrorOnFailure(DecodeMRPParametersIfPresent(TLV::ContextTag(ToRaw(Sigma1Tags::kInitiatorMRPParams)), tlvReader)); - output.initiatorMrpParamsPresent = true; + ReturnErrorOnFailure(DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams), tlvReader)); + outParsedSigma1.initiatorMrpParamsPresent = true; err = tlvReader.Next(); } @@ -2348,20 +2336,20 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, bool resumptionIDTagFound = false; bool resume1MICTagFound = false; - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kResumptionID))) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kResumptionID)) { resumptionIDTagFound = true; - ReturnErrorOnFailure(tlvReader.GetByteView(output.resumptionId)); - VerifyOrReturnError(output.resumptionId.size() == SessionResumptionStorage::kResumptionIdSize, + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.resumptionId)); + VerifyOrReturnError(outParsedSigma1.resumptionId.size() == SessionResumptionStorage::kResumptionIdSize, CHIP_ERROR_INVALID_CASE_PARAMETER); err = tlvReader.Next(); } - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == ContextTag(ToRaw(Sigma1Tags::kResume1MIC))) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kResume1MIC)) { resume1MICTagFound = true; - ReturnErrorOnFailure(tlvReader.GetByteView(output.initiatorResumeMICSpan)); - VerifyOrReturnError(output.initiatorResumeMICSpan.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorResumeMICSpan)); + VerifyOrReturnError(outParsedSigma1.initiatorResumeMICSpan.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INVALID_CASE_PARAMETER); err = tlvReader.Next(); } @@ -2377,11 +2365,11 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, if (resumptionIDTagFound && resume1MICTagFound) { - output.sessionResumptionRequested = true; + outParsedSigma1.sessionResumptionRequested = true; } else if (!resumptionIDTagFound && !resume1MICTagFound) { - output.sessionResumptionRequested = false; + outParsedSigma1.sessionResumptionRequested = false; } else { diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 1394df4eb37558..3827410f6af590 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -231,7 +231,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, uint8_t responderRandom[kSigmaParamRandomNumberSize]; uint16_t responderSessionId; const Crypto::P256PublicKey * pEphPubKey = nullptr; - Platform::ScopedMemoryBuffer msg_R2_Encrypted; + Platform::ScopedMemoryBuffer msgR2Encrypted; size_t encrypted2Length = 0; const ReliableMessageProtocolConfig * responderMrpConfig; }; @@ -331,8 +331,8 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR PrepareSigma2(EncodeSigma2Inputs & output); CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResInputs & output); - CHIP_ERROR SendSigma2(System::PacketBufferHandle & msg_R2); - CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle & msg_R2_resume); + CHIP_ERROR SendSigma2(System::PacketBufferHandle && msg_R2); + CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle && msg_R2_resume); CHIP_ERROR HandleSigma2_and_SendSigma3(System::PacketBufferHandle && msg); CHIP_ERROR HandleSigma2(System::PacketBufferHandle && msg); From bd0252a86609a2ed66bc541a087fbb49d9d092d7 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 20 Dec 2024 17:50:54 +0100 Subject: [PATCH 12/16] Integrating more comments --- src/protocols/secure_channel/CASESession.cpp | 142 ++++++++-------- src/protocols/secure_channel/CASESession.h | 53 +++--- .../secure_channel/tests/TestCASESession.cpp | 151 +++++++++++------- 3 files changed, 192 insertions(+), 154 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 9fe5de5a7eed7d..b9fa5ea79e109f 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -50,7 +50,8 @@ #include namespace { - +// TBEDataTags works for both sigma-2-tbedata and sigma-3-tbedata as they have the same tag numbers for the elements common between +// them. enum class TBEDataTags : uint8_t { kSenderNOC = 1, @@ -59,6 +60,8 @@ enum class TBEDataTags : uint8_t kResumptionID = 4, }; +// TBSDataTags works for both sigma-2-tbsdata and sigma-3-tbsdata as they have the same tag numbers for the elements common between +// them. enum class TBSDataTags : uint8_t { kSenderNOC = 1, @@ -69,30 +72,30 @@ enum class TBSDataTags : uint8_t enum class Sigma1Tags : uint8_t { - kInitiatorRandom = 1, - kInitiatorSessionId = 2, - kDestinationId = 3, - kInitiatorPubKey = 4, - kInitiatorMRPParams = 5, - kResumptionID = 6, - kResume1MIC = 7, + kInitiatorRandom = 1, + kInitiatorSessionId = 2, + kDestinationId = 3, + kInitiatorEphPubKey = 4, + kInitiatorSessionParams = 5, + kResumptionID = 6, + kResume1MIC = 7, }; enum class Sigma2Tags : uint8_t { - kResponderRandom = 1, - kResponderSessionId = 2, - kResponderEphPubKey = 3, - kEncrypted2 = 4, - kResponderMRPParams = 5, + kResponderRandom = 1, + kResponderSessionId = 2, + kResponderEphPubKey = 3, + kEncrypted2 = 4, + kResponderSessionParams = 5, }; -enum class Sigma2ResTags : uint8_t +enum class Sigma2ResumeTags : uint8_t { - kResumptionID = 1, - kSigma2ResumeMIC = 2, - kResponderSessionID = 3, - kResponderMRPParams = 4, + kResumptionID = 1, + kSigma2ResumeMIC = 2, + kResponderSessionID = 3, + kResponderSessionParams = 4, }; enum class Sigma3Tags : uint8_t @@ -104,7 +107,7 @@ enum class Sigma3Tags : uint8_t template constexpr chip::TLV::Tag AsTlvContextTag(Enum e) { - return chip::TLV::ContextTag(static_cast>(e)); + return chip::TLV::ContextTag(chip::to_underlying(e)); } } // namespace @@ -794,7 +797,6 @@ CHIP_ERROR CASESession::SendSigma1() { MATTER_TRACE_SCOPE("SendSigma1", "CASESession"); - System::PacketBufferHandle msgR1; uint8_t destinationIdentifier[kSHA256_Hash_Length] = { 0 }; // Struct that will be used as input to EncodeSigma1() method @@ -812,7 +814,7 @@ CHIP_ERROR CASESession::SendSigma1() mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); - encodeSigma1Inputs.pEphPubKey = &mEphemeralKey->Pubkey(); + encodeSigma1Inputs.initiatorEphPubKey = &mEphemeralKey->Pubkey(); // Fill in the random value ReturnErrorOnFailure(DRBG_get_bytes(mInitiatorRandom, sizeof(mInitiatorRandom))); @@ -847,7 +849,7 @@ CHIP_ERROR CASESession::SendSigma1() { // Found valid resumption state, try to resume the session. encodeSigma1Inputs.resumptionId = mResumeResumptionId; - MutableByteSpan resumeMICSpan(encodeSigma1Inputs.initiatorResume1MIC); + MutableByteSpan resumeMICSpan(encodeSigma1Inputs.initiatorResume1MICBuffer); ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Inputs.initiatorRandom, encodeSigma1Inputs.resumptionId, ByteSpan(kKDFS1RKeyInfo), ByteSpan(kResume1MIC_Nonce), resumeMICSpan)); @@ -856,6 +858,8 @@ CHIP_ERROR CASESession::SendSigma1() } } + System::PacketBufferHandle msgR1; + // Encode Sigma1 in CHIP TLV Format ReturnErrorOnFailure(EncodeSigma1(msgR1, encodeSigma1Inputs)); @@ -893,9 +897,9 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig { MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); - // the PacketBufferHandler should be empty + // The API Contract requires the passed PacketBufferHandle to be empty VerifyOrReturnError(msg.IsNull(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.initiatorEphPubKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT); size_t dataLen = EstimateStructOverhead(kSigmaParamRandomNumberSize, // initiatorRandom sizeof(uint16_t), // initiatorSessionId, @@ -910,20 +914,20 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriter; - TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriter.Init(std::move(msg)); + + TLVType outerContainerType = kTLVType_NotSpecified; ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kInitiatorRandom), input.initiatorRandom)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kInitiatorSessionId), input.initiatorSessionId)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kDestinationId), input.destinationId)); - ReturnErrorOnFailure(tlvWriter.PutBytes(AsTlvContextTag(Sigma1Tags::kInitiatorPubKey), *input.pEphPubKey, - static_cast(input.pEphPubKey->Length()))); + ReturnErrorOnFailure(tlvWriter.PutBytes(AsTlvContextTag(Sigma1Tags::kInitiatorEphPubKey), *input.initiatorEphPubKey, + static_cast(input.initiatorEphPubKey->Length()))); - VerifyOrReturnError(input.initiatorMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.initiatorMrpConfig != nullptr, CHIP_ERROR_INVALID_ARGUMENT); ReturnErrorOnFailure( - EncodeSessionParameters(AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams), *input.initiatorMrpConfig, tlvWriter)); + EncodeSessionParameters(AsTlvContextTag(Sigma1Tags::kInitiatorSessionParams), *input.initiatorMrpConfig, tlvWriter)); if (input.sessionResumptionRequested) { @@ -942,21 +946,22 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & MATTER_TRACE_SCOPE("HandleSigma1_and_SendSigma2", "CASESession"); CHIP_ERROR err = CHIP_NO_ERROR; + Step nextStep = Step::kNone; // Parse and Validate Received Sigma1, and decide next step - SuccessOrExit(err = HandleSigma1(std::move(msg))); + SuccessOrExit(err = HandleSigma1(std::move(msg), nextStep)); - switch (mNextStep) + switch (nextStep) { case Step::kSendSigma2: { System::PacketBufferHandle msgR2; EncodeSigma2Inputs encodeSigma2; - MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); - SuccessOrExit(err = PrepareSigma2(encodeSigma2)); SuccessOrExit(err = EncodeSigma2(msgR2, encodeSigma2)); + + MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2); SuccessOrExitAction(err = SendSigma2(std::move(msgR2)), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2, err)); mDelegate->OnSessionEstablishmentStarted(); @@ -965,12 +970,12 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & case Step::kSendSigma2Resume: { System::PacketBufferHandle msgR2Resume; - EncodeSigma2ResInputs encodeSigma2Resume; - - MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); + EncodeSigma2ResumeInputs encodeSigma2Resume; SuccessOrExit(err = PrepareSigma2Resume(encodeSigma2Resume)); SuccessOrExit(err = EncodeSigma2Resume(msgR2Resume, encodeSigma2Resume)); + + MATTER_LOG_METRIC_BEGIN(kMetricDeviceCASESessionSigma2Resume); SuccessOrExitAction(err = SendSigma2Resume(std::move(msgR2Resume)), MATTER_LOG_METRIC_END(kMetricDeviceCASESessionSigma2Resume, err)); @@ -1077,8 +1082,7 @@ CHIP_ERROR CASESession::TryResumeSession(SessionResumptionStorage::ConstResumpti return CHIP_NO_ERROR; } - -CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) +CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg, Step & nextStep) { MATTER_TRACE_SCOPE("HandleSigma1", "CASESession"); ChipLogProgress(SecureChannel, "Received Sigma1 msg"); @@ -1088,8 +1092,6 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); - CHIP_ERROR err = CHIP_NO_ERROR; - System::PacketBufferTLVReader tlvReader; tlvReader.Init(std::move(msg)); @@ -1118,7 +1120,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) std::copy(parsedSigma1.resumptionId.begin(), parsedSigma1.resumptionId.end(), mResumeResumptionId.begin()); // Next Step is to send Sigma2Resume message to the initiator - mNextStep = Step::kSendSigma2Resume; + nextStep = Step::kSendSigma2Resume; // Early returning here, since the next Step is known to be Sigma2Resume, and no further processing is needed for the // Sigma1 message @@ -1129,6 +1131,8 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) // mRemotePubKey.Length() == initiatorPubKey.size() == kP256_PublicKey_Length. memcpy(mRemotePubKey.Bytes(), parsedSigma1.initiatorEphPubKey.data(), mRemotePubKey.Length()); + CHIP_ERROR err = CHIP_NO_ERROR; + // Attempt to match the initiator's desired destination based on local fabric table. err = FindLocalNodeFromDestinationId(parsedSigma1.destinationId, parsedSigma1.initiatorRandom); if (err == CHIP_NO_ERROR) @@ -1139,7 +1143,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) // Side-effect of FindLocalNodeFromDestinationId success was that mFabricIndex/mLocalNodeId are now // set to the local fabric and associated NodeId that was targeted by the initiator. - mNextStep = Step::kSendSigma2; + nextStep = Step::kSendSigma2; } else { @@ -1148,7 +1152,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if validation of DestinationID fails, which will trigger // status Report with ProtocolCode = NoSharedTrustRoots. - mNextStep = Step::kSendStatusReport; + nextStep = Step::kSendStatusReport; return err; } @@ -1156,7 +1160,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg) return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResInputs & outSigma2ResData) +CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResumeInputs & outSigma2ResData) { MATTER_TRACE_SCOPE("PrepareSigma2Resume", "CASESession"); @@ -1178,13 +1182,13 @@ CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResInputs & outSigma2Res return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Resume, EncodeSigma2ResInputs & input) +CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Resume, EncodeSigma2ResumeInputs & input) { MATTER_TRACE_SCOPE("EncodeSigma2Resume", "CASESession"); - // the passed PacketBufferHandler should be empty + // The API Contract requires the passed PacketBufferHandle to be empty VerifyOrReturnError(msgR2Resume.IsNull(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INVALID_ARGUMENT); size_t maxDatalLen = EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, // sigma2ResumeMIC @@ -1196,17 +1200,17 @@ CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Res VerifyOrReturnError(!msgR2Resume.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriter; - TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriter.Init(std::move(msgR2Resume)); + TLVType outerContainerType = kTLVType_NotSpecified; + ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); - ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kResumptionID), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kSigma2ResumeMIC), input.resumeMICSpan)); - ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResTags::kResponderSessionID), input.responderSessionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kResumptionID), input.resumptionId)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kSigma2ResumeMIC), input.resumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kResponderSessionID), input.responderSessionId)); ReturnErrorOnFailure( - EncodeSessionParameters(AsTlvContextTag(Sigma2ResTags::kResponderMRPParams), *input.responderMrpConfig, tlvWriter)); + EncodeSessionParameters(AsTlvContextTag(Sigma2ResumeTags::kResponderSessionParams), *input.responderMrpConfig, tlvWriter)); ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriter.Finalize(&msgR2Resume)); @@ -1257,7 +1261,7 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & outSigma2Data) mEphemeralKey = mFabricsTable->AllocateEphemeralKeypairForCASE(); VerifyOrReturnError(mEphemeralKey != nullptr, CHIP_ERROR_NO_MEMORY); ReturnErrorOnFailure(mEphemeralKey->Initialize(ECPKeyTarget::ECDH)); - outSigma2Data.pEphPubKey = &mEphemeralKey->Pubkey(); + outSigma2Data.responderEphPubKey = &mEphemeralKey->Pubkey(); // Generate a Shared Secret ReturnErrorOnFailure(mEphemeralKey->ECDH_derive_secret(mRemotePubKey, mSharedSecret)); @@ -1301,9 +1305,10 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & outSigma2Data) CHIP_ERROR_NO_MEMORY); TLVWriter tlvWriter; + tlvWriter.Init(outSigma2Data.msgR2Encrypted.Get(), msgR2SignedEncLen); + TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriter.Init(outSigma2Data.msgR2Encrypted.Get(), msgR2SignedEncLen); ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(TBEDataTags::kSenderNOC), nocCert)); if (!icaCert.empty()) @@ -1344,14 +1349,13 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & outSigma2Data) CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msgR2, EncodeSigma2Inputs & input) { - // the PacketBufferHandler should be empty + // The API Contract requires the passed PacketBufferHandle to be empty VerifyOrReturnError(msgR2.IsNull(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(input.pEphPubKey != nullptr, CHIP_ERROR_INCORRECT_STATE); - // Check if msgR2Encrypted is not nullptr + VerifyOrReturnError(input.responderEphPubKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(input.msgR2Encrypted, CHIP_ERROR_INCORRECT_STATE); // Check if length of msgR2Encrypted is set and is at least larger than the MIC length VerifyOrReturnError(input.encrypted2Length > CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INVALID_ARGUMENT); size_t dataLen = EstimateStructOverhead(kSigmaParamRandomNumberSize, // responderRandom sizeof(uint16_t), // responderSessionId @@ -1364,23 +1368,25 @@ CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msgR2, EncodeS VerifyOrReturnError(!msgR2.IsNull(), CHIP_ERROR_NO_MEMORY); System::PacketBufferTLVWriter tlvWriterMsg2; + tlvWriterMsg2.Init(std::move(msgR2)); + TLVType outerContainerType = kTLVType_NotSpecified; - tlvWriterMsg2.Init(std::move(msgR2)); ReturnErrorOnFailure(tlvWriterMsg2.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kResponderRandom), &input.responderRandom[0], sizeof(input.responderRandom))); ReturnErrorOnFailure(tlvWriterMsg2.Put(AsTlvContextTag(Sigma2Tags::kResponderSessionId), input.responderSessionId)); - ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kResponderEphPubKey), *input.pEphPubKey, - static_cast(input.pEphPubKey->Length()))); + ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kResponderEphPubKey), *input.responderEphPubKey, + static_cast(input.responderEphPubKey->Length()))); ReturnErrorOnFailure(tlvWriterMsg2.PutBytes(AsTlvContextTag(Sigma2Tags::kEncrypted2), input.msgR2Encrypted.Get(), static_cast(input.encrypted2Length))); + input.msgR2Encrypted.Free(); ReturnErrorOnFailure( - EncodeSessionParameters(AsTlvContextTag(Sigma2Tags::kResponderMRPParams), *input.responderMrpConfig, tlvWriterMsg2)); + EncodeSessionParameters(AsTlvContextTag(Sigma2Tags::kResponderSessionParams), *input.responderMrpConfig, tlvWriterMsg2)); ReturnErrorOnFailure(tlvWriterMsg2.EndContainer(outerContainerType)); ReturnErrorOnFailure(tlvWriterMsg2.Finalize(&msgR2)); @@ -1649,7 +1655,7 @@ CHIP_ERROR CASESession::HandleSigma2(System::PacketBufferHandle && msg) // Retrieve responderMRPParams if present if (tlvReader.Next() != CHIP_END_OF_TLV) { - SuccessOrExit(err = DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma2Tags::kResponderMRPParams), tlvReader)); + SuccessOrExit(err = DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma2Tags::kResponderSessionParams), tlvReader)); mExchangeCtxt.Value()->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters( GetRemoteSessionParameters()); } @@ -2327,15 +2333,15 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.destinationId)); VerifyOrReturnError(outParsedSigma1.destinationId.size() == kSHA256_Hash_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); - ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kInitiatorPubKey))); + ReturnErrorOnFailure(tlvReader.Next(AsTlvContextTag(Sigma1Tags::kInitiatorEphPubKey))); ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorEphPubKey)); VerifyOrReturnError(outParsedSigma1.initiatorEphPubKey.size() == kP256_PublicKey_Length, CHIP_ERROR_INVALID_CASE_PARAMETER); // Optional members start here. CHIP_ERROR err = tlvReader.Next(); - if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams)) + if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kInitiatorSessionParams)) { - ReturnErrorOnFailure(DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma1Tags::kInitiatorMRPParams), tlvReader)); + ReturnErrorOnFailure(DecodeMRPParametersIfPresent(AsTlvContextTag(Sigma1Tags::kInitiatorSessionParams), tlvReader)); outParsedSigma1.initiatorMrpParamsPresent = true; err = tlvReader.Next(); diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 3827410f6af590..bb87b614c5050b 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -191,7 +191,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, bool InvokeBackgroundWorkWatchdog(); protected: - // Helper Enum for usage in HandleSigma1_and_SendSigma2 + // Helper Enum for use in HandleSigma1_and_SendSigma2 enum class Step : uint8_t { kNone, @@ -199,10 +199,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, kSendSigma2Resume, kSendStatusReport }; - - Step mNextStep = Step::kNone; - - // This struct only serves as a base struct for EncodeSigma1 and ParseSigma1 + // This struct only serves as a base struct for EncodedSigma1Inputs and ParsedSigma1 struct Sigma1Param { ByteSpan initiatorRandom; @@ -215,9 +212,9 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, struct EncodeSigma1Inputs : Sigma1Param { - const Crypto::P256PublicKey * pEphPubKey = nullptr; + const Crypto::P256PublicKey * initiatorEphPubKey = nullptr; const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr; - uint8_t initiatorResume1MIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + uint8_t initiatorResume1MICBuffer[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; }; struct ParsedSigma1 : Sigma1Param @@ -230,32 +227,35 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, { uint8_t responderRandom[kSigmaParamRandomNumberSize]; uint16_t responderSessionId; - const Crypto::P256PublicKey * pEphPubKey = nullptr; + const Crypto::P256PublicKey * responderEphPubKey = nullptr; + // ScopedMemoryBufferWithSize is not used for msgR2Encrypted since encrypted2Length might differ from the allocated buffer + // size Platform::ScopedMemoryBuffer msgR2Encrypted; size_t encrypted2Length = 0; const ReliableMessageProtocolConfig * responderMrpConfig; }; - struct EncodeSigma2ResInputs + struct EncodeSigma2ResumeInputs { ByteSpan resumptionId; - uint8_t sigma2ResumeMIC[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - MutableByteSpan resumeMICSpan{ sigma2ResumeMIC }; + uint8_t sigma2ResumeMICBuffer[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; + MutableByteSpan resumeMICSpan{ sigma2ResumeMICBuffer }; uint16_t responderSessionId; const ReliableMessageProtocolConfig * responderMrpConfig; }; /** - * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle + *outparam. * * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. * * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. + * @note the passed PacketBufferHandle `outMsg` must not be holding an existing PacketBuffer. **/ - CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); + static CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); /** * Parse a sigma1 message. This function will return success only if the @@ -264,19 +264,21 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * * The required tags are present. * * The values for the tags that are present satisfy schema requirements * (e.g. constraints on octet string lengths) - * * Either resumptionID and initiatorResume1MIC are both present or both + * * Either resumptionID and initiatorResume1MICBuffer are both present or both * absent. * * On success, the members of outParam will be set to the values corresponding to the message. + * These values will be valid as long as the buffer that the passed-in tlvReader is reading from is valid. * - * On success, either the sessionResumptionRequested outParam will be set to true - * and the resumptionID and initiatorResumeMICSpan outparams will be set to - * valid values, or the sessionResumptionRequested outParam will be set to false. + * On success, either the sessionResumptionRequested field will be set to true + * and the resumptionID and initiatorResumeMICSpan fields will be set to + * valid values, or the sessionResumptionRequested field will be set to false. */ - CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & outParam); + CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & parsedMessage); /** - * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle + *outparam. * * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. @@ -286,10 +288,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ - CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); + static CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); /** - * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it within the provided PacketBufferHandle. + * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it, which is owned by the + *PacketBufferHandle outparam. * * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, * as a new buffer will be allocated and assigned to it within the method. @@ -298,7 +301,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ - CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResInputs & inParam); + static CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResumeInputs & inParam); private: friend class TestCASESession; @@ -325,12 +328,12 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR SendSigma1(); CHIP_ERROR HandleSigma1_and_SendSigma2(System::PacketBufferHandle && msg); - CHIP_ERROR HandleSigma1(System::PacketBufferHandle && msg); + CHIP_ERROR HandleSigma1(System::PacketBufferHandle && ms, Step & nextStep); CHIP_ERROR TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC, ByteSpan initiatorRandom); CHIP_ERROR PrepareSigma2(EncodeSigma2Inputs & output); - CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResInputs & output); + CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResumeInputs & output); CHIP_ERROR SendSigma2(System::PacketBufferHandle && msg_R2); CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle && msg_R2_resume); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index f2b4d084fadf26..96bf272161237f 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -59,7 +59,24 @@ using namespace chip::Crypto; namespace chip { class TestCASESecurePairingDelegate; -class TestCASESession : public Test::LoopbackMessagingContext, public CASESession +// Exposing CASESession's Protected members in order to be able to call the protected methods, and instantiate protected structures. +// Also to be able to instantiate New CASESessions repeatedly inside a single TestCase (which is not possible if we inherit +// CASESession in the Test Fixture) +class CASESessionAccess : public CASESession +{ +public: + using CASESession::EncodeSigma1Inputs; + using CASESession::EncodeSigma2Inputs; + using CASESession::EncodeSigma2ResumeInputs; + using CASESession::ParsedSigma1; + + using CASESession::EncodeSigma1; + using CASESession::EncodeSigma2; + using CASESession::EncodeSigma2Resume; + using CASESession::ParseSigma1; +}; + +class TestCASESession : public Test::LoopbackMessagingContext { public: // Performs shared setup for all tests in the test suite @@ -743,9 +760,10 @@ static CHIP_ERROR EncodeSigma1Helper(MutableByteSpan & buf) \ TLV::ContiguousBufferTLVReader reader; \ reader.Init(buf); \ - ParsedSigma1 parsedSigma1; \ + CASESessionAccess session; \ + CASESessionAccess::ParsedSigma1 parsedSigma1; \ \ - EXPECT_EQ(ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::kExpectSuccess); \ + EXPECT_EQ(session.ParseSigma1(reader, parsedSigma1) == CHIP_NO_ERROR, params::kExpectSuccess); \ if (params::kExpectSuccess) \ { \ EXPECT_EQ(parsedSigma1.sessionResumptionRequested, \ @@ -866,181 +884,192 @@ TEST_F(TestCASESession, Sigma1ParsingTest) TEST_F(TestCASESession, EncodeSigma1Test) { - CASESession::EncodeSigma1Inputs encodeParams; + CASESessionAccess::EncodeSigma1Inputs encodeParams; uint8_t random[32]; - EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], 32), CHIP_NO_ERROR); + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], sizeof(random)), CHIP_NO_ERROR); encodeParams.initiatorRandom = ByteSpan(random, sizeof(random)); encodeParams.initiatorSessionId = 7315; uint8_t destinationId[32] = { 0xDE, 0xAD }; encodeParams.destinationId = ByteSpan(destinationId, sizeof(destinationId)); - ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); - encodeParams.initiatorMrpConfig = &MRPConfig; + ReliableMessageProtocolConfig mrpConfig = GetDefaultMRPConfig(); + encodeParams.initiatorMrpConfig = &mrpConfig; { System::PacketBufferHandle msg; // EncodeSigma1 should fail when there is no public key - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, CASESessionAccess::EncodeSigma1(msg, encodeParams)); } - Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); - ASSERT_NE(EphemeralKey, nullptr); - EXPECT_EQ(CHIP_NO_ERROR, EphemeralKey->Initialize(ECPKeyTarget::ECDH)); - encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + Crypto::P256Keypair * ephemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); + ASSERT_NE(ephemeralKey, nullptr); + EXPECT_EQ(CHIP_NO_ERROR, ephemeralKey->Initialize(ECPKeyTarget::ECDH)); + encodeParams.initiatorEphPubKey = &ephemeralKey->Pubkey(); { System::PacketBufferHandle msg; // EncodeSigma1 will Succeed when Public Key is provided - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma1(msg, encodeParams)); } { System::PacketBufferHandle msg; // EncodeSigma1 should fail when MRP config is missing encodeParams.initiatorMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, CASESessionAccess::EncodeSigma1(msg, encodeParams)); } { System::PacketBufferHandle msg; // Succeed when MRP Config is provided - encodeParams.initiatorMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg, encodeParams)); + encodeParams.initiatorMrpConfig = &mrpConfig; + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma1(msg, encodeParams)); } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma1 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma1(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma1(nonEmptyMsg, encodeParams)); } { System::PacketBufferHandle msg1; - System::PacketBufferTLVReader tlvReader; - CASESession::ParsedSigma1 parseParams; // Round Trip Test: Encode Sigma1, Parse it then verify parsed values - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg1, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma1(msg1, encodeParams)); + System::PacketBufferTLVReader tlvReader; tlvReader.Init(std::move(msg1)); - EXPECT_EQ(CHIP_NO_ERROR, ParseSigma1(tlvReader, parseParams)); + + CASESessionAccess session; + CASESessionAccess::ParsedSigma1 parseParams; + + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); // compare parsed values with original values EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( - ByteSpan(encodeParams.pEphPubKey->ConstBytes(), encodeParams.pEphPubKey->Length()))); + ByteSpan(encodeParams.initiatorEphPubKey->ConstBytes(), encodeParams.initiatorEphPubKey->Length()))); } { - System::PacketBufferHandle msg2; - System::PacketBufferTLVReader tlvReader; - CASESession::ParsedSigma1 parseParams; - // Round Trip Test: Sigma1 with Session Resumption // Encode Sigma1 with Resumption, parse it and and verify with original values chip::SessionResumptionStorage::ResumptionIdStorage resumptionId; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(resumptionId.data(), resumptionId.size()), CHIP_NO_ERROR); - EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.initiatorResume1MIC[0], sizeof(encodeParams.initiatorResume1MIC)), + EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.initiatorResume1MICBuffer[0], + sizeof(encodeParams.initiatorResume1MICBuffer)), CHIP_NO_ERROR); encodeParams.resumptionId = ByteSpan(resumptionId.data(), resumptionId.size()); - encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MIC); + encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MICBuffer); encodeParams.sessionResumptionRequested = true; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma1(msg2, encodeParams)); + System::PacketBufferHandle msg2; - // Encode and Parse Round Trip Test + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma1(msg2, encodeParams)); + + System::PacketBufferTLVReader tlvReader; tlvReader.Init(std::move(msg2)); - EXPECT_EQ(CHIP_NO_ERROR, ParseSigma1(tlvReader, parseParams)); + CASESessionAccess session; + CASESessionAccess::ParsedSigma1 parseParams; + + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); // RoundTrip EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( - ByteSpan(encodeParams.pEphPubKey->ConstBytes(), encodeParams.pEphPubKey->Length()))); + ByteSpan(encodeParams.initiatorEphPubKey->ConstBytes(), encodeParams.initiatorEphPubKey->Length()))); EXPECT_TRUE(parseParams.resumptionId.data_equal(encodeParams.resumptionId)); EXPECT_TRUE(parseParams.initiatorResumeMICSpan.data_equal(encodeParams.initiatorResumeMICSpan)); EXPECT_TRUE(parseParams.initiatorMrpParamsPresent); } // Release EphemeralKeyPair - gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); + gDeviceOperationalKeystore.ReleaseEphemeralKeypair(ephemeralKey); } TEST_F(TestCASESession, EncodeSigma2Test) { - CASESession::EncodeSigma2Inputs encodeParams; + CASESessionAccess::EncodeSigma2Inputs encodeParams; constexpr uint8_t kEncrypted2datalen = 100U; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&encodeParams.responderRandom[0], sizeof(encodeParams.responderRandom)), CHIP_NO_ERROR); encodeParams.responderSessionId = 7315; // Generate Ephemeral Public Key - Crypto::P256Keypair * EphemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); - ASSERT_NE(EphemeralKey, nullptr); - EXPECT_EQ(CHIP_NO_ERROR, EphemeralKey->Initialize(ECPKeyTarget::ECDH)); - encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + Crypto::P256Keypair * ephemeralKey = gDeviceOperationalKeystore.AllocateEphemeralKeypairForCASE(); + ASSERT_NE(ephemeralKey, nullptr); + EXPECT_EQ(CHIP_NO_ERROR, ephemeralKey->Initialize(ECPKeyTarget::ECDH)); + encodeParams.responderEphPubKey = &ephemeralKey->Pubkey(); // TBEData2Encrypted encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); // responder Session Parameters - ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); - encodeParams.responderMrpConfig = &MRPConfig; + ReliableMessageProtocolConfig mrpConfig = GetDefaultMRPConfig(); + encodeParams.responderMrpConfig = &mrpConfig; { System::PacketBufferHandle msg; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2(msg, encodeParams)); + // EncodeSigma2 frees msgR2Encrypted after encoding it + encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma2 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2(nonEmptyMsg, encodeParams)); } { System::PacketBufferHandle msg; // EncodeSigma2 should fail when there is no public key - encodeParams.pEphPubKey = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + encodeParams.responderEphPubKey = nullptr; + EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, CASESessionAccess::EncodeSigma2(msg, encodeParams)); } - encodeParams.pEphPubKey = &EphemeralKey->Pubkey(); + encodeParams.responderEphPubKey = &ephemeralKey->Pubkey(); { System::PacketBufferHandle msg; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2(msg, encodeParams)); + // EncodeSigma2 frees msgR2Encrypted after encoding it + encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); } { System::PacketBufferHandle msg; // EncodeSigma2 should fail when TBEData2Encrypted is not allocated encodeParams.msgR2Encrypted.Free(); - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2(msg, encodeParams)); } encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); { System::PacketBufferHandle msg; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2(msg, encodeParams)); + // EncodeSigma2 frees msgR2Encrypted after encoding it + encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); } { System::PacketBufferHandle msg; // EncodeSigma2 should fail when the encrypted2Length is not set encodeParams.encrypted2Length = 0; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2(msg, encodeParams)); } // Set encrypted2Length again encodeParams.encrypted2Length = kEncrypted2datalen + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES; @@ -1049,53 +1078,53 @@ TEST_F(TestCASESession, EncodeSigma2Test) System::PacketBufferHandle msg; // EncodeSigma2 should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, CASESessionAccess::EncodeSigma2(msg, encodeParams)); } { System::PacketBufferHandle msg; // Succeed when MRP Config is provided - encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2(msg, encodeParams)); + encodeParams.responderMrpConfig = &mrpConfig; + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2(msg, encodeParams)); } // Release EphemeralKeyPair - gDeviceOperationalKeystore.ReleaseEphemeralKeypair(EphemeralKey); + gDeviceOperationalKeystore.ReleaseEphemeralKeypair(ephemeralKey); } TEST_F(TestCASESession, EncodeSigma2ResumeTest) { - CASESession::EncodeSigma2ResInputs encodeParams; + CASESessionAccess::EncodeSigma2ResumeInputs encodeParams; encodeParams.responderSessionId = 7315; // responder Session Parameters - ReliableMessageProtocolConfig MRPConfig = GetDefaultMRPConfig(); - encodeParams.responderMrpConfig = &MRPConfig; + ReliableMessageProtocolConfig mrpConfig = GetDefaultMRPConfig(); + encodeParams.responderMrpConfig = &mrpConfig; { System::PacketBufferHandle msg; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2Resume(msg, encodeParams)); } { System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); // EncodeSigma2Resume should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(nonEmptyMsg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2Resume(nonEmptyMsg, encodeParams)); } { System::PacketBufferHandle msg; // EncodeSigma2Resume should fail when MRP config is missing encodeParams.responderMrpConfig = nullptr; - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, EncodeSigma2Resume(msg, encodeParams)); + EXPECT_EQ(CHIP_ERROR_INVALID_ARGUMENT, CASESessionAccess::EncodeSigma2Resume(msg, encodeParams)); } { System::PacketBufferHandle msg; // Succeed when MRP Config is provided - encodeParams.responderMrpConfig = &MRPConfig; - EXPECT_EQ(CHIP_NO_ERROR, EncodeSigma2Resume(msg, encodeParams)); + encodeParams.responderMrpConfig = &mrpConfig; + EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2Resume(msg, encodeParams)); } } From 264ba3e1ee141bc8e2b1af569bacbacf07699df4 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 20 Dec 2024 19:19:17 +0100 Subject: [PATCH 13/16] Using a Variant for the NextStep logic in HandleSigma1, to either send a Sigma message or a status report --- src/lib/support/CodeUtils.h | 28 ++++++++++++++++ src/protocols/secure_channel/CASESession.cpp | 35 ++++++++------------ src/protocols/secure_channel/CASESession.h | 7 ++-- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index 01cc80bffcbe6c..0d8ad3b0bff7cb 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -156,6 +156,34 @@ } \ } while (false) +/** + * @def ReturnErrorVariantOnFailure(expr) + * + * @brief + * This is for use when the caller function returns a Variant type. It returns a CHIP_ERROR variant with the corresponding error + * code if the expression returns an error. For a CHIP_ERROR expression, this means any value other + * than CHIP_NO_ERROR. For an integer expression, this means non-zero. + * + * Example usage: + * + * @code + * ReturnErrorVariantOnFailure(NextStep, ParseSigma1(tlvReader, parsedSigma1)); + * @endcode + * + * @param[in] variantType The Variant type that the calling function returns. + * @param[in] expr An expression to be tested. + + */ +#define ReturnErrorVariantOnFailure(variantType, expr) \ + do \ + { \ + auto __err = (expr); \ + if (!::chip::ChipError::IsSuccess(__err)) \ + { \ + return variantType::Create(__err); \ + } \ + } while (false) + /** * @def ReturnLogErrorOnFailure(expr) * diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index b9fa5ea79e109f..ee32a4d8fc02cc 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -946,12 +946,12 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & MATTER_TRACE_SCOPE("HandleSigma1_and_SendSigma2", "CASESession"); CHIP_ERROR err = CHIP_NO_ERROR; - Step nextStep = Step::kNone; // Parse and Validate Received Sigma1, and decide next step - SuccessOrExit(err = HandleSigma1(std::move(msg), nextStep)); + NextStep nextStep = HandleSigma1(std::move(msg)); + VerifyOrExit(nextStep.Is(), err = nextStep.Get()); - switch (nextStep) + switch (nextStep.Get()) { case Step::kSendSigma2: { @@ -982,15 +982,11 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & mDelegate->OnSessionEstablishmentStarted(); break; } - // TODO should I keep this? - case Step::kSendStatusReport: default: - ExitNow(); break; } exit: - if (err == CHIP_ERROR_KEY_NOT_FOUND) { SendStatusReport(mExchangeCtxt, kProtocolCodeNoSharedRoot); @@ -1082,15 +1078,15 @@ CHIP_ERROR CASESession::TryResumeSession(SessionResumptionStorage::ConstResumpti return CHIP_NO_ERROR; } -CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg, Step & nextStep) +CASESession::NextStep CASESession::HandleSigma1(System::PacketBufferHandle && msg) { MATTER_TRACE_SCOPE("HandleSigma1", "CASESession"); ChipLogProgress(SecureChannel, "Received Sigma1 msg"); MATTER_TRACE_COUNTER("Sigma1"); - VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mFabricsTable != nullptr, NextStep::Create(CHIP_ERROR_INCORRECT_STATE)); - ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); + ReturnErrorVariantOnFailure(NextStep, mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() })); System::PacketBufferTLVReader tlvReader; tlvReader.Init(std::move(msg)); @@ -1098,7 +1094,7 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg, Step & n // Struct that will serve as output in ParseSigma1 ParsedSigma1 parsedSigma1; - ReturnErrorOnFailure(ParseSigma1(tlvReader, parsedSigma1)); + ReturnErrorVariantOnFailure(NextStep, ParseSigma1(tlvReader, parsedSigma1)); ChipLogDetail(SecureChannel, "Peer assigned session key ID %d", parsedSigma1.initiatorSessionId); SetPeerSessionId(parsedSigma1.initiatorSessionId); @@ -1119,12 +1115,9 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg, Step & n std::copy(parsedSigma1.initiatorRandom.begin(), parsedSigma1.initiatorRandom.end(), mInitiatorRandom); std::copy(parsedSigma1.resumptionId.begin(), parsedSigma1.resumptionId.end(), mResumeResumptionId.begin()); - // Next Step is to send Sigma2Resume message to the initiator - nextStep = Step::kSendSigma2Resume; - // Early returning here, since the next Step is known to be Sigma2Resume, and no further processing is needed for the // Sigma1 message - return CHIP_NO_ERROR; + return NextStep::Create(Step::kSendSigma2Resume); } // ParseSigma1 ensures that: @@ -1143,21 +1136,21 @@ CHIP_ERROR CASESession::HandleSigma1(System::PacketBufferHandle && msg, Step & n // Side-effect of FindLocalNodeFromDestinationId success was that mFabricIndex/mLocalNodeId are now // set to the local fabric and associated NodeId that was targeted by the initiator. - nextStep = Step::kSendSigma2; + return NextStep::Create(Step::kSendSigma2); } else { ChipLogError(SecureChannel, "CASE failed to match destination ID with local fabrics"); ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); - // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if validation of DestinationID fails, which will trigger - // status Report with ProtocolCode = NoSharedTrustRoots. - nextStep = Step::kSendStatusReport; + // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if Sigma1's DestinationId does not match any + // candidateDestinationId, this will trigger a status Report with ProtocolCode = NoSharedTrustRoots. - return err; + // Returning a CHIP_ERROR variant that will trigger a corresponding Status Report. + return NextStep::Create(err); } - return CHIP_NO_ERROR; + return NextStep::Create(CHIP_NO_ERROR); } CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResumeInputs & outSigma2ResData) diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index bb87b614c5050b..99b50a8daca4d4 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -197,8 +197,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, kNone, kSendSigma2, kSendSigma2Resume, - kSendStatusReport }; + // Making NextStep a Variant allows HandleSigma() to return either a Step value (indicating + // the next Sigma step to send) or a CHIP_ERROR (indicating a failure that will trigger + // a Status Report). + using NextStep = Variant; // This struct only serves as a base struct for EncodedSigma1Inputs and ParsedSigma1 struct Sigma1Param { @@ -328,7 +331,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR SendSigma1(); CHIP_ERROR HandleSigma1_and_SendSigma2(System::PacketBufferHandle && msg); - CHIP_ERROR HandleSigma1(System::PacketBufferHandle && ms, Step & nextStep); + NextStep HandleSigma1(System::PacketBufferHandle && msg); CHIP_ERROR TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC, ByteSpan initiatorRandom); From 993edbd3aff2cd7000e5d3da6fc2f92ca2fbe416 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 20 Dec 2024 20:07:20 +0100 Subject: [PATCH 14/16] fixing clang-tidy error --- src/lib/support/CodeUtils.h | 2 +- src/protocols/secure_channel/CASESession.cpp | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index 0d8ad3b0bff7cb..cb3591956b3bc0 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -160,7 +160,7 @@ * @def ReturnErrorVariantOnFailure(expr) * * @brief - * This is for use when the caller function returns a Variant type. It returns a CHIP_ERROR variant with the corresponding error + * This is for use when the calling function returns a Variant type. It returns a CHIP_ERROR variant with the corresponding error * code if the expression returns an error. For a CHIP_ERROR expression, this means any value other * than CHIP_NO_ERROR. For an integer expression, this means non-zero. * diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index ee32a4d8fc02cc..bcee5597a7c8c8 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -1138,19 +1138,15 @@ CASESession::NextStep CASESession::HandleSigma1(System::PacketBufferHandle && ms return NextStep::Create(Step::kSendSigma2); } - else - { - ChipLogError(SecureChannel, "CASE failed to match destination ID with local fabrics"); - ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); - // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if Sigma1's DestinationId does not match any - // candidateDestinationId, this will trigger a status Report with ProtocolCode = NoSharedTrustRoots. + ChipLogError(SecureChannel, "CASE failed to match destination ID with local fabrics"); + ChipLogByteSpan(SecureChannel, parsedSigma1.destinationId); - // Returning a CHIP_ERROR variant that will trigger a corresponding Status Report. - return NextStep::Create(err); - } + // FindLocalNodeFromDestinationId returns CHIP_ERROR_KEY_NOT_FOUND if Sigma1's DestinationId does not match any + // candidateDestinationId, this will trigger a status Report with ProtocolCode = NoSharedTrustRoots. - return NextStep::Create(CHIP_NO_ERROR); + // Returning a CHIP_ERROR variant that will trigger a corresponding Status Report. + return NextStep::Create(err); } CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResumeInputs & outSigma2ResData) From 6a9068f615f0edeaaa6f8ae633f057e8d69173a5 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Fri, 20 Dec 2024 20:32:42 +0100 Subject: [PATCH 15/16] more comments --- src/protocols/secure_channel/CASESession.cpp | 16 ++++-------- src/protocols/secure_channel/CASESession.h | 19 ++++++-------- .../secure_channel/tests/TestCASESession.cpp | 25 ++----------------- 3 files changed, 15 insertions(+), 45 deletions(-) diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index bcee5597a7c8c8..46a8b887203bb9 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -853,7 +853,7 @@ CHIP_ERROR CASESession::SendSigma1() ReturnErrorOnFailure(GenerateSigmaResumeMIC(encodeSigma1Inputs.initiatorRandom, encodeSigma1Inputs.resumptionId, ByteSpan(kKDFS1RKeyInfo), ByteSpan(kResume1MIC_Nonce), resumeMICSpan)); - encodeSigma1Inputs.initiatorResumeMICSpan = resumeMICSpan; + encodeSigma1Inputs.initiatorResumeMIC = resumeMICSpan; encodeSigma1Inputs.sessionResumptionRequested = true; } } @@ -897,8 +897,6 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig { MATTER_TRACE_SCOPE("EncodeSigma1", "CASESession"); - // The API Contract requires the passed PacketBufferHandle to be empty - VerifyOrReturnError(msg.IsNull(), CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(input.initiatorEphPubKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT); size_t dataLen = EstimateStructOverhead(kSigmaParamRandomNumberSize, // initiatorRandom @@ -932,7 +930,7 @@ CHIP_ERROR CASESession::EncodeSigma1(System::PacketBufferHandle & msg, EncodeSig if (input.sessionResumptionRequested) { ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kResumptionID), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kResume1MIC), input.initiatorResumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma1Tags::kResume1MIC), input.initiatorResumeMIC)); } ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType)); @@ -1110,7 +1108,7 @@ CASESession::NextStep CASESession::HandleSigma1(System::PacketBufferHandle && ms parsedSigma1.resumptionId.size() == SessionResumptionStorage::kResumptionIdSize && CHIP_NO_ERROR == TryResumeSession(SessionResumptionStorage::ConstResumptionIdView(parsedSigma1.resumptionId.data()), - parsedSigma1.initiatorResumeMICSpan, parsedSigma1.initiatorRandom)) + parsedSigma1.initiatorResumeMIC, parsedSigma1.initiatorRandom)) { std::copy(parsedSigma1.initiatorRandom.begin(), parsedSigma1.initiatorRandom.end(), mInitiatorRandom); std::copy(parsedSigma1.resumptionId.begin(), parsedSigma1.resumptionId.end(), mResumeResumptionId.begin()); @@ -1175,8 +1173,6 @@ CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Res { MATTER_TRACE_SCOPE("EncodeSigma2Resume", "CASESession"); - // The API Contract requires the passed PacketBufferHandle to be empty - VerifyOrReturnError(msgR2Resume.IsNull(), CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(input.responderMrpConfig != nullptr, CHIP_ERROR_INVALID_ARGUMENT); size_t maxDatalLen = EstimateStructOverhead(SessionResumptionStorage::kResumptionIdSize, // resumptionID @@ -1338,8 +1334,6 @@ CHIP_ERROR CASESession::PrepareSigma2(EncodeSigma2Inputs & outSigma2Data) CHIP_ERROR CASESession::EncodeSigma2(System::PacketBufferHandle & msgR2, EncodeSigma2Inputs & input) { - // The API Contract requires the passed PacketBufferHandle to be empty - VerifyOrReturnError(msgR2.IsNull(), CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(input.responderEphPubKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(input.msgR2Encrypted, CHIP_ERROR_INCORRECT_STATE); // Check if length of msgR2Encrypted is set and is at least larger than the MIC length @@ -2351,8 +2345,8 @@ CHIP_ERROR CASESession::ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, if (err == CHIP_NO_ERROR && tlvReader.GetTag() == AsTlvContextTag(Sigma1Tags::kResume1MIC)) { resume1MICTagFound = true; - ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorResumeMICSpan)); - VerifyOrReturnError(outParsedSigma1.initiatorResumeMICSpan.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, + ReturnErrorOnFailure(tlvReader.GetByteView(outParsedSigma1.initiatorResumeMIC)); + VerifyOrReturnError(outParsedSigma1.initiatorResumeMIC.size() == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, CHIP_ERROR_INVALID_CASE_PARAMETER); err = tlvReader.Next(); } diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 99b50a8daca4d4..8f565eb62c76e4 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -210,7 +210,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, ByteSpan destinationId; bool sessionResumptionRequested = false; ByteSpan resumptionId; - ByteSpan initiatorResumeMICSpan; + ByteSpan initiatorResumeMIC; }; struct EncodeSigma1Inputs : Sigma1Param @@ -251,12 +251,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle *outparam. * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. + * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the + *method. * * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outMsg` must not be holding an existing PacketBuffer. **/ static CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); @@ -274,7 +273,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * These values will be valid as long as the buffer that the passed-in tlvReader is reading from is valid. * * On success, either the sessionResumptionRequested field will be set to true - * and the resumptionID and initiatorResumeMICSpan fields will be set to + * and the resumptionID and initiatorResumeMIC fields will be set to * valid values, or the sessionResumptionRequested field will be set to false. */ CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & parsedMessage); @@ -283,12 +282,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle *outparam. * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. + * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the + *method. * * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ static CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam); @@ -297,12 +295,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it, which is owned by the *PacketBufferHandle outparam. * - * @param outMsg PacketBufferHandle passed by reference. The handle must be empty prior to calling this method, - * as a new buffer will be allocated and assigned to it within the method. + * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the + *method. * * @param inParam a struct containing all the values that will be encoded into TLV format * - * @note the passed PacketBufferHandle `outMsg` must be in a null state. **/ static CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResumeInputs & inParam); diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index 96bf272161237f..c0b28df137652f 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -927,13 +927,6 @@ TEST_F(TestCASESession, EncodeSigma1Test) EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma1(msg, encodeParams)); } - { - System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); - - // EncodeSigma1 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma1(nonEmptyMsg, encodeParams)); - } - { System::PacketBufferHandle msg1; @@ -967,7 +960,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) CHIP_NO_ERROR); encodeParams.resumptionId = ByteSpan(resumptionId.data(), resumptionId.size()); - encodeParams.initiatorResumeMICSpan = ByteSpan(encodeParams.initiatorResume1MICBuffer); + encodeParams.initiatorResumeMIC = ByteSpan(encodeParams.initiatorResume1MICBuffer); encodeParams.sessionResumptionRequested = true; System::PacketBufferHandle msg2; @@ -990,7 +983,7 @@ TEST_F(TestCASESession, EncodeSigma1Test) ByteSpan(encodeParams.initiatorEphPubKey->ConstBytes(), encodeParams.initiatorEphPubKey->Length()))); EXPECT_TRUE(parseParams.resumptionId.data_equal(encodeParams.resumptionId)); - EXPECT_TRUE(parseParams.initiatorResumeMICSpan.data_equal(encodeParams.initiatorResumeMICSpan)); + EXPECT_TRUE(parseParams.initiatorResumeMIC.data_equal(encodeParams.initiatorResumeMIC)); EXPECT_TRUE(parseParams.initiatorMrpParamsPresent); } // Release EphemeralKeyPair @@ -1026,13 +1019,6 @@ TEST_F(TestCASESession, EncodeSigma2Test) encodeParams.msgR2Encrypted.Alloc(encodeParams.encrypted2Length); } - { - System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); - - // EncodeSigma2 should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2(nonEmptyMsg, encodeParams)); - } - { System::PacketBufferHandle msg; @@ -1106,13 +1092,6 @@ TEST_F(TestCASESession, EncodeSigma2ResumeTest) EXPECT_EQ(CHIP_NO_ERROR, CASESessionAccess::EncodeSigma2Resume(msg, encodeParams)); } - { - System::PacketBufferHandle nonEmptyMsg = System::PacketBufferHandle::New(100); - - // EncodeSigma2Resume should fail when the packetBufferHandle passed to it is not empty - EXPECT_EQ(CHIP_ERROR_INCORRECT_STATE, CASESessionAccess::EncodeSigma2Resume(nonEmptyMsg, encodeParams)); - } - { System::PacketBufferHandle msg; // EncodeSigma2Resume should fail when MRP config is missing From db95d7cfe112791b2bdc2e565c8a63e0645d4730 Mon Sep 17 00:00:00 2001 From: Alami-Amine Date: Mon, 23 Dec 2024 15:37:12 +0100 Subject: [PATCH 16/16] comments integration --- src/lib/support/CodeUtils.h | 3 +- src/protocols/secure_channel/CASESession.cpp | 4 +-- src/protocols/secure_channel/CASESession.h | 21 ++++++------ .../secure_channel/tests/TestCASESession.cpp | 34 +++++++++---------- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index cb3591956b3bc0..cd07370fa92ec4 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -161,8 +161,7 @@ * * @brief * This is for use when the calling function returns a Variant type. It returns a CHIP_ERROR variant with the corresponding error - * code if the expression returns an error. For a CHIP_ERROR expression, this means any value other - * than CHIP_NO_ERROR. For an integer expression, this means non-zero. + * code if the expression returns an error. * * Example usage: * diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 46a8b887203bb9..6242cc2aa6199c 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -1162,7 +1162,7 @@ CHIP_ERROR CASESession::PrepareSigma2Resume(EncodeSigma2ResumeInputs & outSigma2 outSigma2ResData.resumptionId = mNewResumptionId; ReturnErrorOnFailure(GenerateSigmaResumeMIC(ByteSpan(mInitiatorRandom), mNewResumptionId, ByteSpan(kKDFS2RKeyInfo), - ByteSpan(kResume2MIC_Nonce), outSigma2ResData.resumeMICSpan)); + ByteSpan(kResume2MIC_Nonce), outSigma2ResData.resumeMIC)); outSigma2ResData.responderMrpConfig = &mLocalMRPConfig.Value(); @@ -1191,7 +1191,7 @@ CHIP_ERROR CASESession::EncodeSigma2Resume(System::PacketBufferHandle & msgR2Res ReturnErrorOnFailure(tlvWriter.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainerType)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kResumptionID), input.resumptionId)); - ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kSigma2ResumeMIC), input.resumeMICSpan)); + ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kSigma2ResumeMIC), input.resumeMIC)); ReturnErrorOnFailure(tlvWriter.Put(AsTlvContextTag(Sigma2ResumeTags::kResponderSessionID), input.responderSessionId)); ReturnErrorOnFailure( diff --git a/src/protocols/secure_channel/CASESession.h b/src/protocols/secure_channel/CASESession.h index 8f565eb62c76e4..a9d43194d0f56d 100644 --- a/src/protocols/secure_channel/CASESession.h +++ b/src/protocols/secure_channel/CASESession.h @@ -194,7 +194,6 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, // Helper Enum for use in HandleSigma1_and_SendSigma2 enum class Step : uint8_t { - kNone, kSendSigma2, kSendSigma2Resume, }; @@ -202,7 +201,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, // the next Sigma step to send) or a CHIP_ERROR (indicating a failure that will trigger // a Status Report). using NextStep = Variant; - // This struct only serves as a base struct for EncodedSigma1Inputs and ParsedSigma1 + // This struct only serves as a base struct for EncodeSigma1Inputs and ParsedSigma1 struct Sigma1Param { ByteSpan initiatorRandom; @@ -242,17 +241,17 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, { ByteSpan resumptionId; uint8_t sigma2ResumeMICBuffer[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]; - MutableByteSpan resumeMICSpan{ sigma2ResumeMICBuffer }; + MutableByteSpan resumeMIC{ sigma2ResumeMICBuffer }; uint16_t responderSessionId; const ReliableMessageProtocolConfig * responderMrpConfig; }; /** * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle - *outparam. + * outparam. * * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the - *method. + * method. * * @param inParam a struct containing all the values that will be encoded into TLV format * @@ -260,13 +259,13 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, static CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam); /** - * Parse a sigma1 message. This function will return success only if the + * Parse a Sigma1 message. This function will return success only if the * message passes schema checks. Specifically: * * The tags come in order. * * The required tags are present. * * The values for the tags that are present satisfy schema requirements * (e.g. constraints on octet string lengths) - * * Either resumptionID and initiatorResume1MICBuffer are both present or both + * * Either resumptionID and initiatorResume1MICBuffer are both present or both are * absent. * * On success, the members of outParam will be set to the values corresponding to the message. @@ -280,10 +279,10 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, /** * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle - *outparam. + * outparam. * * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the - *method. + * method. * * @param inParam a struct containing all the values that will be encoded into TLV format * @@ -293,10 +292,10 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler, /** * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it, which is owned by the - *PacketBufferHandle outparam. + * PacketBufferHandle outparam. * * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the - *method. + * method. * * @param inParam a struct containing all the values that will be encoded into TLV format * diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index c0b28df137652f..81a2142c716021 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -888,10 +888,10 @@ TEST_F(TestCASESession, EncodeSigma1Test) uint8_t random[32]; EXPECT_EQ(chip::Crypto::DRBG_get_bytes(&random[0], sizeof(random)), CHIP_NO_ERROR); - encodeParams.initiatorRandom = ByteSpan(random, sizeof(random)); + encodeParams.initiatorRandom = ByteSpan(random); encodeParams.initiatorSessionId = 7315; uint8_t destinationId[32] = { 0xDE, 0xAD }; - encodeParams.destinationId = ByteSpan(destinationId, sizeof(destinationId)); + encodeParams.destinationId = ByteSpan(destinationId); ReliableMessageProtocolConfig mrpConfig = GetDefaultMRPConfig(); encodeParams.initiatorMrpConfig = &mrpConfig; @@ -937,15 +937,15 @@ TEST_F(TestCASESession, EncodeSigma1Test) tlvReader.Init(std::move(msg1)); CASESessionAccess session; - CASESessionAccess::ParsedSigma1 parseParams; + CASESessionAccess::ParsedSigma1 parsedMessage; - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parsedMessage)); // compare parsed values with original values - EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); - EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); - EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); - EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( + EXPECT_TRUE(parsedMessage.initiatorRandom.data_equal(encodeParams.initiatorRandom)); + EXPECT_EQ(parsedMessage.initiatorSessionId, encodeParams.initiatorSessionId); + EXPECT_TRUE(parsedMessage.destinationId.data_equal(encodeParams.destinationId)); + EXPECT_TRUE(parsedMessage.initiatorEphPubKey.data_equal( ByteSpan(encodeParams.initiatorEphPubKey->ConstBytes(), encodeParams.initiatorEphPubKey->Length()))); } @@ -971,20 +971,20 @@ TEST_F(TestCASESession, EncodeSigma1Test) tlvReader.Init(std::move(msg2)); CASESessionAccess session; - CASESessionAccess::ParsedSigma1 parseParams; + CASESessionAccess::ParsedSigma1 parsedMessage; - EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parseParams)); + EXPECT_EQ(CHIP_NO_ERROR, session.ParseSigma1(tlvReader, parsedMessage)); // RoundTrip - EXPECT_TRUE(parseParams.initiatorRandom.data_equal(encodeParams.initiatorRandom)); - EXPECT_EQ(parseParams.initiatorSessionId, encodeParams.initiatorSessionId); - EXPECT_TRUE(parseParams.destinationId.data_equal(encodeParams.destinationId)); - EXPECT_TRUE(parseParams.initiatorEphPubKey.data_equal( + EXPECT_TRUE(parsedMessage.initiatorRandom.data_equal(encodeParams.initiatorRandom)); + EXPECT_EQ(parsedMessage.initiatorSessionId, encodeParams.initiatorSessionId); + EXPECT_TRUE(parsedMessage.destinationId.data_equal(encodeParams.destinationId)); + EXPECT_TRUE(parsedMessage.initiatorEphPubKey.data_equal( ByteSpan(encodeParams.initiatorEphPubKey->ConstBytes(), encodeParams.initiatorEphPubKey->Length()))); - EXPECT_TRUE(parseParams.resumptionId.data_equal(encodeParams.resumptionId)); - EXPECT_TRUE(parseParams.initiatorResumeMIC.data_equal(encodeParams.initiatorResumeMIC)); - EXPECT_TRUE(parseParams.initiatorMrpParamsPresent); + EXPECT_TRUE(parsedMessage.resumptionId.data_equal(encodeParams.resumptionId)); + EXPECT_TRUE(parsedMessage.initiatorResumeMIC.data_equal(encodeParams.initiatorResumeMIC)); + EXPECT_TRUE(parsedMessage.initiatorMrpParamsPresent); } // Release EphemeralKeyPair gDeviceOperationalKeystore.ReleaseEphemeralKeypair(ephemeralKey);