LCOV - code coverage report
Current view: top level - protocols/secure_channel - PASESession.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 409 444 92.1 %
Date: 2024-02-15 08:20:41 Functions: 22 25 88.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2022 Project CHIP Authors
       4             :  *    All rights reserved.
       5             :  *
       6             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7             :  *    you may not use this file except in compliance with the License.
       8             :  *    You may obtain a copy of the License at
       9             :  *
      10             :  *        http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  *    Unless required by applicable law or agreed to in writing, software
      13             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  *    See the License for the specific language governing permissions and
      16             :  *    limitations under the License.
      17             :  */
      18             : 
      19             : /**
      20             :  *    @file
      21             :  *      This file implements the CHIP SPAKE2P Session object that provides
      22             :  *      APIs for constructing spake2p messages and establishing encryption
      23             :  *      keys.
      24             :  *
      25             :  *      The protocol for handling pA, pB, cB and cA is defined in SPAKE2
      26             :  *      Plus specifications.
      27             :  *      (https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html)
      28             :  *
      29             :  */
      30             : #include <protocols/secure_channel/PASESession.h>
      31             : 
      32             : #include <inttypes.h>
      33             : #include <string.h>
      34             : 
      35             : #include <lib/core/CHIPEncoding.h>
      36             : #include <lib/core/CHIPSafeCasts.h>
      37             : #include <lib/support/BufferWriter.h>
      38             : #include <lib/support/CHIPMem.h>
      39             : #include <lib/support/CodeUtils.h>
      40             : #include <lib/support/SafeInt.h>
      41             : #include <lib/support/TypeTraits.h>
      42             : #include <messaging/SessionParameters.h>
      43             : #include <protocols/Protocols.h>
      44             : #include <protocols/secure_channel/Constants.h>
      45             : #include <protocols/secure_channel/StatusReport.h>
      46             : #include <setup_payload/SetupPayload.h>
      47             : #include <system/TLVPacketBufferBackingStore.h>
      48             : #include <tracing/macros.h>
      49             : #include <transport/SessionManager.h>
      50             : 
      51             : namespace chip {
      52             : 
      53             : using namespace Crypto;
      54             : using namespace Messaging;
      55             : using namespace Protocols::SecureChannel;
      56             : 
      57             : const char kSpake2pContext[]        = "CHIP PAKE V1 Commissioning";
      58             : const char kSpake2pI2RSessionInfo[] = "Commissioning I2R Key";
      59             : const char kSpake2pR2ISessionInfo[] = "Commissioning R2I Key";
      60             : 
      61             : // Amounts of time to allow for server-side processing of messages.
      62             : //
      63             : // These timeout values only allow for the server-side processing and assume that any transport-specific
      64             : // latency will be added to them.
      65             : //
      66             : // The session establishment fails if the response is not received within the resulting timeout window,
      67             : // which accounts for both transport latency and the server-side latency.
      68             : static constexpr ExchangeContext::Timeout kExpectedLowProcessingTime  = System::Clock::Seconds16(2);
      69             : static constexpr ExchangeContext::Timeout kExpectedHighProcessingTime = System::Clock::Seconds16(30);
      70             : 
      71          16 : PASESession::~PASESession()
      72             : {
      73             :     // Let's clear out any security state stored in the object, before destroying it.
      74          16 :     Clear();
      75          16 : }
      76             : 
      77          10 : void PASESession::OnSessionReleased()
      78             : {
      79             :     // Call into our super-class before we clear our state.
      80          10 :     PairingSession::OnSessionReleased();
      81          10 :     Clear();
      82          10 : }
      83             : 
      84          10 : void PASESession::Finish()
      85             : {
      86          10 :     mPairingComplete = true;
      87          10 :     PairingSession::Finish();
      88          10 : }
      89             : 
      90          65 : void PASESession::Clear()
      91             : {
      92             :     MATTER_TRACE_SCOPE("Clear", "PASESession");
      93             :     // This function zeroes out and resets the memory used by the object.
      94             :     // It's done so that no security related information will be leaked.
      95          65 :     memset(&mPASEVerifier, 0, sizeof(mPASEVerifier));
      96          65 :     mNextExpectedMsg.ClearValue();
      97             : 
      98          65 :     mSpake2p.Clear();
      99          65 :     mCommissioningHash.Clear();
     100             : 
     101          65 :     mIterationCount = 0;
     102          65 :     mSaltLength     = 0;
     103          65 :     if (mSalt != nullptr)
     104             :     {
     105          14 :         chip::Platform::MemoryFree(mSalt);
     106          14 :         mSalt = nullptr;
     107             :     }
     108          65 :     mPairingComplete = false;
     109          65 :     PairingSession::Clear();
     110          65 : }
     111             : 
     112          22 : CHIP_ERROR PASESession::Init(SessionManager & sessionManager, uint32_t setupCode, SessionEstablishmentDelegate * delegate)
     113             : {
     114             :     MATTER_TRACE_SCOPE("Init", "PASESession");
     115          22 :     VerifyOrReturnError(sessionManager.GetSessionKeystore() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     116          22 :     VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     117             : 
     118             :     // Reset any state maintained by PASESession object (in case it's being reused for pairing)
     119          22 :     Clear();
     120             : 
     121          22 :     ReturnErrorOnFailure(mCommissioningHash.Begin());
     122          22 :     ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext) }));
     123             : 
     124          22 :     mDelegate = delegate;
     125          22 :     ReturnErrorOnFailure(AllocateSecureSession(sessionManager));
     126          22 :     VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE);
     127          22 :     ChipLogDetail(SecureChannel, "Assigned local session key ID %u", GetLocalSessionId().Value());
     128             : 
     129          22 :     ReturnErrorCodeIf(setupCode >= (1 << kSetupPINCodeFieldLengthInBits), CHIP_ERROR_INVALID_ARGUMENT);
     130          22 :     mSetupPINCode = setupCode;
     131             : 
     132          22 :     return CHIP_NO_ERROR;
     133             : }
     134             : 
     135           0 : CHIP_ERROR PASESession::GeneratePASEVerifier(Spake2pVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt,
     136             :                                              bool useRandomPIN, uint32_t & setupPINCode)
     137             : {
     138             :     MATTER_TRACE_SCOPE("GeneratePASEVerifier", "PASESession");
     139             : 
     140           0 :     if (useRandomPIN)
     141             :     {
     142           0 :         ReturnErrorOnFailure(DRBG_get_bytes(reinterpret_cast<uint8_t *>(&setupPINCode), sizeof(setupPINCode)));
     143             : 
     144             :         // Passcodes shall be restricted to the values 00000001 to 99999998 in decimal, see 5.1.1.6
     145           0 :         setupPINCode = (setupPINCode % kSetupPINCodeMaximumValue) + 1;
     146             :     }
     147             : 
     148           0 :     return verifier.Generate(pbkdf2IterCount, salt, setupPINCode);
     149             : }
     150             : 
     151          12 : CHIP_ERROR PASESession::SetupSpake2p()
     152             : {
     153             :     MATTER_TRACE_SCOPE("SetupSpake2p", "PASESession");
     154          12 :     uint8_t context[kSHA256_Hash_Length] = { 0 };
     155          12 :     MutableByteSpan contextSpan{ context };
     156             : 
     157          12 :     ReturnErrorOnFailure(mCommissioningHash.Finish(contextSpan));
     158          12 :     ReturnErrorOnFailure(mSpake2p.Init(contextSpan.data(), contextSpan.size()));
     159             : 
     160          12 :     return CHIP_NO_ERROR;
     161             : }
     162             : 
     163          17 : CHIP_ERROR PASESession::WaitForPairing(SessionManager & sessionManager, const Spake2pVerifier & verifier, uint32_t pbkdf2IterCount,
     164             :                                        const ByteSpan & salt, Optional<ReliableMessageProtocolConfig> mrpLocalConfig,
     165             :                                        SessionEstablishmentDelegate * delegate)
     166             : {
     167             :     // Return early on error here, as we have not initialized any state yet
     168          17 :     ReturnErrorCodeIf(salt.empty(), CHIP_ERROR_INVALID_ARGUMENT);
     169          16 :     ReturnErrorCodeIf(salt.data() == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     170          16 :     ReturnErrorCodeIf(salt.size() < kSpake2p_Min_PBKDF_Salt_Length || salt.size() > kSpake2p_Max_PBKDF_Salt_Length,
     171             :                       CHIP_ERROR_INVALID_ARGUMENT);
     172             : 
     173          14 :     CHIP_ERROR err = Init(sessionManager, kSetupPINCodeUndefinedValue, delegate);
     174             :     // From here onwards, let's go to exit on error, as some state might have already
     175             :     // been initialized
     176          14 :     SuccessOrExit(err);
     177             : 
     178          14 :     mRole = CryptoContext::SessionRole::kResponder;
     179             : 
     180          14 :     VerifyOrExit(CanCastTo<uint16_t>(salt.size()), err = CHIP_ERROR_INVALID_ARGUMENT);
     181          14 :     mSaltLength = static_cast<uint16_t>(salt.size());
     182             : 
     183          14 :     if (mSalt != nullptr)
     184             :     {
     185           0 :         chip::Platform::MemoryFree(mSalt);
     186           0 :         mSalt = nullptr;
     187             :     }
     188             : 
     189          14 :     mSalt = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(mSaltLength));
     190          14 :     VerifyOrExit(mSalt != nullptr, err = CHIP_ERROR_NO_MEMORY);
     191             : 
     192          14 :     memmove(mSalt, salt.data(), mSaltLength);
     193          14 :     memmove(&mPASEVerifier, &verifier, sizeof(verifier));
     194             : 
     195          14 :     mIterationCount = pbkdf2IterCount;
     196          14 :     mNextExpectedMsg.SetValue(MsgType::PBKDFParamRequest);
     197          14 :     mPairingComplete = false;
     198          14 :     mLocalMRPConfig  = mrpLocalConfig;
     199             : 
     200          14 :     ChipLogDetail(SecureChannel, "Waiting for PBKDF param request");
     201             : 
     202           0 : exit:
     203          14 :     if (err != CHIP_NO_ERROR)
     204             :     {
     205           0 :         Clear();
     206             :     }
     207          14 :     return err;
     208             : }
     209             : 
     210           9 : CHIP_ERROR PASESession::Pair(SessionManager & sessionManager, uint32_t peerSetUpPINCode,
     211             :                              Optional<ReliableMessageProtocolConfig> mrpLocalConfig, Messaging::ExchangeContext * exchangeCtxt,
     212             :                              SessionEstablishmentDelegate * delegate)
     213             : {
     214             :     MATTER_TRACE_SCOPE("Pair", "PASESession");
     215           9 :     ReturnErrorCodeIf(exchangeCtxt == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     216           8 :     CHIP_ERROR err = Init(sessionManager, peerSetUpPINCode, delegate);
     217           8 :     SuccessOrExit(err);
     218             : 
     219           8 :     mRole = CryptoContext::SessionRole::kInitiator;
     220             : 
     221           8 :     mExchangeCtxt = exchangeCtxt;
     222             : 
     223             :     // When commissioning starts, the peer is assumed to be active.
     224           8 :     mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->MarkActiveRx();
     225             : 
     226           8 :     mExchangeCtxt->UseSuggestedResponseTimeout(kExpectedLowProcessingTime);
     227             : 
     228           8 :     mLocalMRPConfig = mrpLocalConfig;
     229             : 
     230           8 :     err = SendPBKDFParamRequest();
     231           8 :     SuccessOrExit(err);
     232             : 
     233           7 :     mDelegate->OnSessionEstablishmentStarted();
     234             : 
     235           8 : exit:
     236           8 :     if (err != CHIP_NO_ERROR)
     237             :     {
     238           1 :         Clear();
     239             :     }
     240           8 :     return err;
     241             : }
     242             : 
     243           0 : void PASESession::OnResponseTimeout(ExchangeContext * ec)
     244             : {
     245             :     MATTER_TRACE_SCOPE("OnResponseTimeout", "PASESession");
     246           0 :     VerifyOrReturn(ec != nullptr, ChipLogError(SecureChannel, "PASESession::OnResponseTimeout was called by null exchange"));
     247           0 :     VerifyOrReturn(mExchangeCtxt == nullptr || mExchangeCtxt == ec,
     248             :                    ChipLogError(SecureChannel, "PASESession::OnResponseTimeout exchange doesn't match"));
     249             :     // If we were waiting for something, mNextExpectedMsg had better have a value.
     250           0 :     ChipLogError(SecureChannel, "PASESession timed out while waiting for a response from the peer. Expected message type was %u",
     251             :                  to_underlying(mNextExpectedMsg.Value()));
     252             :     MATTER_TRACE_COUNTER("PASETimeout");
     253             :     // Discard the exchange so that Clear() doesn't try closing it.  The
     254             :     // exchange will handle that.
     255           0 :     DiscardExchange();
     256           0 :     Clear();
     257             :     // Do this last in case the delegate frees us.
     258           0 :     NotifySessionEstablishmentError(CHIP_ERROR_TIMEOUT);
     259             : }
     260             : 
     261          10 : CHIP_ERROR PASESession::DeriveSecureSession(CryptoContext & session) const
     262             : {
     263          10 :     VerifyOrReturnError(mPairingComplete, CHIP_ERROR_INCORRECT_STATE);
     264             : 
     265          10 :     SessionKeystore & keystore = *mSessionManager->GetSessionKeystore();
     266          10 :     AutoReleaseSymmetricKey<HkdfKeyHandle> hkdfKey(keystore);
     267             : 
     268          10 :     ReturnErrorOnFailure(mSpake2p.GetKeys(keystore, hkdfKey.KeyHandle()));
     269          10 :     ReturnErrorOnFailure(session.InitFromSecret(keystore, hkdfKey.KeyHandle(), ByteSpan{} /* salt */,
     270             :                                                 CryptoContext::SessionInfoType::kSessionEstablishment, mRole));
     271             : 
     272          10 :     return CHIP_NO_ERROR;
     273          10 : }
     274             : 
     275           8 : CHIP_ERROR PASESession::SendPBKDFParamRequest()
     276             : {
     277             :     MATTER_TRACE_SCOPE("SendPBKDFParamRequest", "PASESession");
     278             : 
     279           8 :     VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE);
     280             : 
     281           8 :     ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
     282             : 
     283           8 :     const size_t max_msg_len = TLV::EstimateStructOverhead(kPBKDFParamRandomNumberSize,         // initiatorRandom,
     284             :                                                            sizeof(uint16_t),                    // initiatorSessionId
     285             :                                                            sizeof(PasscodeId),                  // passcodeId,
     286             :                                                            sizeof(uint8_t),                     // hasPBKDFParameters
     287             :                                                            SessionParameters::kEstimatedTLVSize // Session Parameters
     288             :     );
     289             : 
     290           8 :     System::PacketBufferHandle req = System::PacketBufferHandle::New(max_msg_len);
     291           8 :     VerifyOrReturnError(!req.IsNull(), CHIP_ERROR_NO_MEMORY);
     292             : 
     293           8 :     System::PacketBufferTLVWriter tlvWriter;
     294           8 :     tlvWriter.Init(std::move(req));
     295             : 
     296           8 :     TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     297           8 :     ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     298           8 :     ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(1), mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
     299           8 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), GetLocalSessionId().Value()));
     300           8 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), kDefaultCommissioningPasscodeId));
     301           8 :     ReturnErrorOnFailure(tlvWriter.PutBoolean(TLV::ContextTag(4), mHavePBKDFParameters));
     302             : 
     303           8 :     ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriter));
     304             : 
     305           8 :     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     306           8 :     ReturnErrorOnFailure(tlvWriter.Finalize(&req));
     307             : 
     308             :     // Update commissioning hash with the pbkdf2 param request that's being sent.
     309           8 :     ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ req->Start(), req->DataLength() }));
     310             : 
     311           8 :     ReturnErrorOnFailure(
     312             :         mExchangeCtxt->SendMessage(MsgType::PBKDFParamRequest, std::move(req), SendFlags(SendMessageFlags::kExpectResponse)));
     313             : 
     314           7 :     mNextExpectedMsg.SetValue(MsgType::PBKDFParamResponse);
     315             : 
     316           7 :     ChipLogDetail(SecureChannel, "Sent PBKDF param request");
     317             : 
     318           7 :     return CHIP_NO_ERROR;
     319           8 : }
     320             : 
     321           6 : CHIP_ERROR PASESession::HandlePBKDFParamRequest(System::PacketBufferHandle && msg)
     322             : {
     323             :     MATTER_TRACE_SCOPE("HandlePBKDFParamRequest", "PASESession");
     324           6 :     CHIP_ERROR err = CHIP_NO_ERROR;
     325             : 
     326           6 :     System::PacketBufferTLVReader tlvReader;
     327           6 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     328             : 
     329             :     uint16_t initiatorSessionId;
     330             :     uint8_t initiatorRandom[kPBKDFParamRandomNumberSize];
     331             : 
     332           6 :     uint32_t decodeTagIdSeq = 0;
     333           6 :     PasscodeId passcodeId   = kDefaultCommissioningPasscodeId;
     334           6 :     bool hasPBKDFParameters = false;
     335             : 
     336           6 :     ChipLogDetail(SecureChannel, "Received PBKDF param request");
     337             : 
     338           6 :     SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() }));
     339             : 
     340           6 :     tlvReader.Init(std::move(msg));
     341           6 :     SuccessOrExit(err = tlvReader.Next(containerType, TLV::AnonymousTag()));
     342           6 :     SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     343             : 
     344           6 :     SuccessOrExit(err = tlvReader.Next());
     345           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     346           6 :     SuccessOrExit(err = tlvReader.GetBytes(initiatorRandom, sizeof(initiatorRandom)));
     347             : 
     348           6 :     SuccessOrExit(err = tlvReader.Next());
     349           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     350           6 :     SuccessOrExit(err = tlvReader.Get(initiatorSessionId));
     351             : 
     352           6 :     ChipLogDetail(SecureChannel, "Peer assigned session ID %d", initiatorSessionId);
     353           6 :     SetPeerSessionId(initiatorSessionId);
     354             : 
     355           6 :     SuccessOrExit(err = tlvReader.Next());
     356           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     357           6 :     SuccessOrExit(err = tlvReader.Get(passcodeId));
     358           6 :     VerifyOrExit(passcodeId == kDefaultCommissioningPasscodeId, err = CHIP_ERROR_INVALID_PASE_PARAMETER);
     359             : 
     360           6 :     SuccessOrExit(err = tlvReader.Next());
     361           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     362           6 :     SuccessOrExit(err = tlvReader.Get(hasPBKDFParameters));
     363             : 
     364           6 :     if (tlvReader.Next() != CHIP_END_OF_TLV)
     365             :     {
     366           6 :         SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
     367           6 :         mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters(GetRemoteSessionParameters());
     368             :     }
     369             : 
     370           6 :     err = SendPBKDFParamResponse(ByteSpan(initiatorRandom), hasPBKDFParameters);
     371           6 :     SuccessOrExit(err);
     372             : 
     373           6 :     mDelegate->OnSessionEstablishmentStarted();
     374             : 
     375           6 : exit:
     376             : 
     377           6 :     if (err != CHIP_NO_ERROR)
     378             :     {
     379           0 :         SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam);
     380             :     }
     381           6 :     return err;
     382           6 : }
     383             : 
     384           6 : CHIP_ERROR PASESession::SendPBKDFParamResponse(ByteSpan initiatorRandom, bool initiatorHasPBKDFParams)
     385             : {
     386             :     MATTER_TRACE_SCOPE("SendPBKDFParamResponse", "PASESession");
     387             : 
     388           6 :     VerifyOrReturnError(GetLocalSessionId().HasValue(), CHIP_ERROR_INCORRECT_STATE);
     389             : 
     390           6 :     ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
     391             : 
     392             :     const size_t max_msg_len =
     393           6 :         TLV::EstimateStructOverhead(kPBKDFParamRandomNumberSize,                                // initiatorRandom
     394             :                                     kPBKDFParamRandomNumberSize,                                // responderRandom
     395             :                                     sizeof(uint16_t),                                           // responderSessionId
     396           6 :                                     TLV::EstimateStructOverhead(sizeof(uint32_t), mSaltLength), // pbkdf_parameters
     397             :                                     SessionParameters::kEstimatedTLVSize                        // Session Parameters
     398             :         );
     399             : 
     400           6 :     System::PacketBufferHandle resp = System::PacketBufferHandle::New(max_msg_len);
     401           6 :     VerifyOrReturnError(!resp.IsNull(), CHIP_ERROR_NO_MEMORY);
     402             : 
     403           6 :     System::PacketBufferTLVWriter tlvWriter;
     404           6 :     tlvWriter.Init(std::move(resp));
     405             : 
     406           6 :     TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     407           6 :     ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     408             :     // The initiator random value is being sent back in the response as required by the specifications
     409           6 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), initiatorRandom));
     410           6 :     ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(2), mPBKDFLocalRandomData, sizeof(mPBKDFLocalRandomData)));
     411           6 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), GetLocalSessionId().Value()));
     412             : 
     413           6 :     if (!initiatorHasPBKDFParams)
     414             :     {
     415             :         TLV::TLVType pbkdfParamContainer;
     416           6 :         ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::ContextTag(4), TLV::kTLVType_Structure, pbkdfParamContainer));
     417           6 :         ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), mIterationCount));
     418           6 :         ReturnErrorOnFailure(tlvWriter.PutBytes(TLV::ContextTag(2), mSalt, mSaltLength));
     419           6 :         ReturnErrorOnFailure(tlvWriter.EndContainer(pbkdfParamContainer));
     420             :     }
     421             : 
     422           6 :     ReturnErrorOnFailure(EncodeSessionParameters(TLV::ContextTag(5), mLocalMRPConfig, tlvWriter));
     423             : 
     424           6 :     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     425           6 :     ReturnErrorOnFailure(tlvWriter.Finalize(&resp));
     426             : 
     427             :     // Update commissioning hash with the pbkdf2 param response that's being sent.
     428           6 :     ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ resp->Start(), resp->DataLength() }));
     429           6 :     ReturnErrorOnFailure(SetupSpake2p());
     430             : 
     431           6 :     ReturnErrorOnFailure(
     432             :         mExchangeCtxt->SendMessage(MsgType::PBKDFParamResponse, std::move(resp), SendFlags(SendMessageFlags::kExpectResponse)));
     433           6 :     ChipLogDetail(SecureChannel, "Sent PBKDF param response");
     434             : 
     435           6 :     mNextExpectedMsg.SetValue(MsgType::PASE_Pake1);
     436             : 
     437           6 :     return CHIP_NO_ERROR;
     438           6 : }
     439             : 
     440           6 : CHIP_ERROR PASESession::HandlePBKDFParamResponse(System::PacketBufferHandle && msg)
     441             : {
     442             :     MATTER_TRACE_SCOPE("HandlePBKDFParamResponse", "PASESession");
     443           6 :     CHIP_ERROR err = CHIP_NO_ERROR;
     444             : 
     445           6 :     System::PacketBufferTLVReader tlvReader;
     446           6 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     447             : 
     448             :     uint16_t responderSessionId;
     449             :     uint8_t random[kPBKDFParamRandomNumberSize];
     450             : 
     451           6 :     uint32_t decodeTagIdSeq = 0;
     452           6 :     ByteSpan salt;
     453           6 :     uint8_t serializedWS[kSpake2p_WS_Length * 2] = { 0 };
     454             : 
     455           6 :     ChipLogDetail(SecureChannel, "Received PBKDF param response");
     456             : 
     457           6 :     SuccessOrExit(err = mCommissioningHash.AddData(ByteSpan{ msg->Start(), msg->DataLength() }));
     458             : 
     459           6 :     tlvReader.Init(std::move(msg));
     460           6 :     SuccessOrExit(err = tlvReader.Next(containerType, TLV::AnonymousTag()));
     461           6 :     SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     462             : 
     463           6 :     SuccessOrExit(err = tlvReader.Next());
     464           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     465             :     // Initiator's random value
     466           6 :     SuccessOrExit(err = tlvReader.GetBytes(random, sizeof(random)));
     467           6 :     VerifyOrExit(ByteSpan(random).data_equal(ByteSpan(mPBKDFLocalRandomData)), err = CHIP_ERROR_INVALID_PASE_PARAMETER);
     468             : 
     469           6 :     SuccessOrExit(err = tlvReader.Next());
     470           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     471             :     // Responder's random value
     472           6 :     SuccessOrExit(err = tlvReader.GetBytes(random, sizeof(random)));
     473             : 
     474           6 :     SuccessOrExit(err = tlvReader.Next());
     475           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     476           6 :     SuccessOrExit(err = tlvReader.Get(responderSessionId));
     477             : 
     478           6 :     ChipLogDetail(SecureChannel, "Peer assigned session ID %d", responderSessionId);
     479           6 :     SetPeerSessionId(responderSessionId);
     480             : 
     481           6 :     if (mHavePBKDFParameters)
     482             :     {
     483           0 :         if (tlvReader.Next() != CHIP_END_OF_TLV)
     484             :         {
     485           0 :             SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
     486           0 :             mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters(GetRemoteSessionParameters());
     487             :         }
     488             : 
     489             :         // TODO - Add a unit test that exercises mHavePBKDFParameters path
     490           0 :         salt = ByteSpan(mSalt, mSaltLength);
     491             :     }
     492             :     else
     493             :     {
     494           6 :         SuccessOrExit(err = tlvReader.Next());
     495           6 :         SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     496           6 :         decodeTagIdSeq = 0;
     497             : 
     498           6 :         SuccessOrExit(err = tlvReader.Next());
     499           6 :         VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     500           6 :         SuccessOrExit(err = tlvReader.Get(mIterationCount));
     501             : 
     502           6 :         SuccessOrExit(err = tlvReader.Next());
     503           6 :         VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     504           6 :         SuccessOrExit(err = tlvReader.Get(salt));
     505             : 
     506           6 :         SuccessOrExit(err = tlvReader.ExitContainer(containerType));
     507             : 
     508           6 :         if (tlvReader.Next() != CHIP_END_OF_TLV)
     509             :         {
     510           6 :             SuccessOrExit(err = DecodeMRPParametersIfPresent(TLV::ContextTag(5), tlvReader));
     511           6 :             mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->SetRemoteSessionParameters(GetRemoteSessionParameters());
     512             :         }
     513             :     }
     514             : 
     515           6 :     err = SetupSpake2p();
     516           6 :     SuccessOrExit(err);
     517             : 
     518           6 :     err = Spake2pVerifier::ComputeWS(mIterationCount, salt, mSetupPINCode, serializedWS, sizeof(serializedWS));
     519           6 :     SuccessOrExit(err);
     520             : 
     521           6 :     err = mSpake2p.BeginProver(nullptr, 0, nullptr, 0, &serializedWS[0], kSpake2p_WS_Length, &serializedWS[kSpake2p_WS_Length],
     522             :                                kSpake2p_WS_Length);
     523           6 :     SuccessOrExit(err);
     524             : 
     525           6 :     err = SendMsg1();
     526           6 :     SuccessOrExit(err);
     527             : 
     528           6 : exit:
     529           6 :     if (err != CHIP_NO_ERROR)
     530             :     {
     531           0 :         SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam);
     532             :     }
     533           6 :     return err;
     534           6 : }
     535             : 
     536           6 : CHIP_ERROR PASESession::SendMsg1()
     537             : {
     538             :     MATTER_TRACE_SCOPE("SendMsg1", "PASESession");
     539           6 :     const size_t max_msg_len       = TLV::EstimateStructOverhead(kMAX_Point_Length);
     540           6 :     System::PacketBufferHandle msg = System::PacketBufferHandle::New(max_msg_len);
     541           6 :     VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY);
     542             : 
     543           6 :     System::PacketBufferTLVWriter tlvWriter;
     544           6 :     tlvWriter.Init(std::move(msg));
     545             : 
     546           6 :     TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     547           6 :     ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     548             : 
     549             :     uint8_t X[kMAX_Point_Length];
     550           6 :     size_t X_len = sizeof(X);
     551             : 
     552           6 :     constexpr uint8_t kPake1_pA = 1;
     553             : 
     554           6 :     ReturnErrorOnFailure(mSpake2p.ComputeRoundOne(nullptr, 0, X, &X_len));
     555           6 :     VerifyOrReturnError(X_len == sizeof(X), CHIP_ERROR_INTERNAL);
     556           6 :     ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(kPake1_pA), ByteSpan(X)));
     557           6 :     ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
     558           6 :     ReturnErrorOnFailure(tlvWriter.Finalize(&msg));
     559             : 
     560           6 :     ReturnErrorOnFailure(
     561             :         mExchangeCtxt->SendMessage(MsgType::PASE_Pake1, std::move(msg), SendFlags(SendMessageFlags::kExpectResponse)));
     562           6 :     ChipLogDetail(SecureChannel, "Sent spake2p msg1");
     563             : 
     564           6 :     mNextExpectedMsg.SetValue(MsgType::PASE_Pake2);
     565             : 
     566           6 :     return CHIP_NO_ERROR;
     567           6 : }
     568             : 
     569           6 : CHIP_ERROR PASESession::HandleMsg1_and_SendMsg2(System::PacketBufferHandle && msg1)
     570             : {
     571             :     MATTER_TRACE_SCOPE("HandleMsg1_and_SendMsg2", "PASESession");
     572           6 :     CHIP_ERROR err = CHIP_NO_ERROR;
     573             : 
     574             :     uint8_t Y[kMAX_Point_Length];
     575           6 :     size_t Y_len = sizeof(Y);
     576             : 
     577             :     uint8_t verifier[kMAX_Hash_Length];
     578           6 :     size_t verifier_len = kMAX_Hash_Length;
     579             : 
     580           6 :     ChipLogDetail(SecureChannel, "Received spake2p msg1");
     581             :     MATTER_TRACE_SCOPE("Pake1", "PASESession");
     582             : 
     583           6 :     System::PacketBufferTLVReader tlvReader;
     584           6 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     585             : 
     586             :     const uint8_t * X;
     587           6 :     size_t X_len = 0;
     588             : 
     589           6 :     tlvReader.Init(std::move(msg1));
     590           6 :     SuccessOrExit(err = tlvReader.Next(containerType, TLV::AnonymousTag()));
     591           6 :     SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     592             : 
     593           6 :     SuccessOrExit(err = tlvReader.Next());
     594           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == 1, err = CHIP_ERROR_INVALID_TLV_TAG);
     595           6 :     X_len = tlvReader.GetLength();
     596           6 :     SuccessOrExit(err = tlvReader.GetDataPtr(X));
     597           6 :     SuccessOrExit(err = mSpake2p.BeginVerifier(nullptr, 0, nullptr, 0, mPASEVerifier.mW0, kP256_FE_Length, mPASEVerifier.mL,
     598             :                                                kP256_Point_Length));
     599             : 
     600           6 :     SuccessOrExit(err = mSpake2p.ComputeRoundOne(X, X_len, Y, &Y_len));
     601           6 :     VerifyOrReturnError(Y_len == sizeof(Y), CHIP_ERROR_INTERNAL);
     602           6 :     SuccessOrExit(err = mSpake2p.ComputeRoundTwo(X, X_len, verifier, &verifier_len));
     603           6 :     msg1 = nullptr;
     604             : 
     605             :     {
     606           6 :         const size_t max_msg_len    = TLV::EstimateStructOverhead(Y_len, verifier_len);
     607           6 :         constexpr uint8_t kPake2_pB = 1;
     608           6 :         constexpr uint8_t kPake2_cB = 2;
     609             : 
     610           6 :         System::PacketBufferHandle msg2 = System::PacketBufferHandle::New(max_msg_len);
     611           6 :         VerifyOrExit(!msg2.IsNull(), err = CHIP_ERROR_NO_MEMORY);
     612             : 
     613           6 :         System::PacketBufferTLVWriter tlvWriter;
     614           6 :         tlvWriter.Init(std::move(msg2));
     615             : 
     616           6 :         TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     617           6 :         SuccessOrExit(err = tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     618           6 :         SuccessOrExit(err = tlvWriter.Put(TLV::ContextTag(kPake2_pB), ByteSpan(Y)));
     619           6 :         SuccessOrExit(err = tlvWriter.Put(TLV::ContextTag(kPake2_cB), ByteSpan(verifier, verifier_len)));
     620           6 :         SuccessOrExit(err = tlvWriter.EndContainer(outerContainerType));
     621           6 :         SuccessOrExit(err = tlvWriter.Finalize(&msg2));
     622             : 
     623           6 :         err = mExchangeCtxt->SendMessage(MsgType::PASE_Pake2, std::move(msg2), SendFlags(SendMessageFlags::kExpectResponse));
     624           6 :         SuccessOrExit(err);
     625             : 
     626           6 :         mNextExpectedMsg.SetValue(MsgType::PASE_Pake3);
     627           6 :     }
     628             : 
     629           6 :     ChipLogDetail(SecureChannel, "Sent spake2p msg2");
     630             :     MATTER_TRACE_COUNTER("Pake2");
     631             : 
     632           0 : exit:
     633             : 
     634           6 :     if (err != CHIP_NO_ERROR)
     635             :     {
     636           0 :         SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam);
     637             :     }
     638           6 :     return err;
     639           6 : }
     640             : 
     641           6 : CHIP_ERROR PASESession::HandleMsg2_and_SendMsg3(System::PacketBufferHandle && msg2)
     642             : {
     643             :     MATTER_TRACE_SCOPE("HandleMsg2_and_SendMsg3", "PASESession");
     644           6 :     CHIP_ERROR err = CHIP_NO_ERROR;
     645             : 
     646             :     uint8_t verifier[kMAX_Hash_Length];
     647           6 :     size_t verifier_len = kMAX_Hash_Length;
     648             : 
     649           6 :     System::PacketBufferHandle resp;
     650             : 
     651           6 :     ChipLogDetail(SecureChannel, "Received spake2p msg2");
     652             : 
     653           6 :     System::PacketBufferTLVReader tlvReader;
     654           6 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     655             : 
     656             :     const uint8_t * Y;
     657           6 :     size_t Y_len = 0;
     658             : 
     659             :     const uint8_t * peer_verifier;
     660           6 :     size_t peer_verifier_len = 0;
     661             : 
     662           6 :     uint32_t decodeTagIdSeq = 0;
     663             : 
     664           6 :     tlvReader.Init(std::move(msg2));
     665           6 :     SuccessOrExit(err = tlvReader.Next(containerType, TLV::AnonymousTag()));
     666           6 :     SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     667             : 
     668           6 :     SuccessOrExit(err = tlvReader.Next());
     669           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     670           6 :     Y_len = tlvReader.GetLength();
     671           6 :     SuccessOrExit(err = tlvReader.GetDataPtr(Y));
     672             : 
     673           6 :     SuccessOrExit(err = tlvReader.Next());
     674           6 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == ++decodeTagIdSeq, err = CHIP_ERROR_INVALID_TLV_TAG);
     675           6 :     peer_verifier_len = tlvReader.GetLength();
     676           6 :     SuccessOrExit(err = tlvReader.GetDataPtr(peer_verifier));
     677             : 
     678           6 :     SuccessOrExit(err = mSpake2p.ComputeRoundTwo(Y, Y_len, verifier, &verifier_len));
     679             : 
     680           6 :     SuccessOrExit(err = mSpake2p.KeyConfirm(peer_verifier, peer_verifier_len));
     681           5 :     msg2 = nullptr;
     682             : 
     683             :     {
     684           5 :         const size_t max_msg_len    = TLV::EstimateStructOverhead(verifier_len);
     685           5 :         constexpr uint8_t kPake3_cB = 1;
     686             : 
     687           5 :         System::PacketBufferHandle msg3 = System::PacketBufferHandle::New(max_msg_len);
     688           5 :         VerifyOrExit(!msg3.IsNull(), err = CHIP_ERROR_NO_MEMORY);
     689             : 
     690           5 :         System::PacketBufferTLVWriter tlvWriter;
     691           5 :         tlvWriter.Init(std::move(msg3));
     692             : 
     693           5 :         TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
     694           5 :         SuccessOrExit(err = tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
     695           5 :         SuccessOrExit(err = tlvWriter.Put(TLV::ContextTag(kPake3_cB), ByteSpan(verifier, verifier_len)));
     696           5 :         SuccessOrExit(err = tlvWriter.EndContainer(outerContainerType));
     697           5 :         SuccessOrExit(err = tlvWriter.Finalize(&msg3));
     698             : 
     699           5 :         err = mExchangeCtxt->SendMessage(MsgType::PASE_Pake3, std::move(msg3), SendFlags(SendMessageFlags::kExpectResponse));
     700           5 :         SuccessOrExit(err);
     701             : 
     702           5 :         mNextExpectedMsg.SetValue(MsgType::StatusReport);
     703           5 :     }
     704           5 :     ChipLogDetail(SecureChannel, "Sent spake2p msg3");
     705             : 
     706           0 : exit:
     707             : 
     708           6 :     if (err != CHIP_NO_ERROR)
     709             :     {
     710           1 :         SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam);
     711             :     }
     712           6 :     return err;
     713           6 : }
     714             : 
     715           5 : CHIP_ERROR PASESession::HandleMsg3(System::PacketBufferHandle && msg)
     716             : {
     717             :     MATTER_TRACE_SCOPE("HandleMsg3", "PASESession");
     718           5 :     CHIP_ERROR err = CHIP_NO_ERROR;
     719             : 
     720           5 :     ChipLogDetail(SecureChannel, "Received spake2p msg3");
     721             :     MATTER_TRACE_COUNTER("Pake3");
     722             : 
     723           5 :     mNextExpectedMsg.ClearValue();
     724             : 
     725           5 :     System::PacketBufferTLVReader tlvReader;
     726           5 :     TLV::TLVType containerType = TLV::kTLVType_Structure;
     727             : 
     728             :     const uint8_t * peer_verifier;
     729           5 :     size_t peer_verifier_len = 0;
     730             : 
     731           5 :     tlvReader.Init(std::move(msg));
     732           5 :     SuccessOrExit(err = tlvReader.Next(containerType, TLV::AnonymousTag()));
     733           5 :     SuccessOrExit(err = tlvReader.EnterContainer(containerType));
     734             : 
     735           5 :     SuccessOrExit(err = tlvReader.Next());
     736           5 :     VerifyOrExit(TLV::TagNumFromTag(tlvReader.GetTag()) == 1, err = CHIP_ERROR_INVALID_TLV_TAG);
     737           5 :     peer_verifier_len = tlvReader.GetLength();
     738           5 :     SuccessOrExit(err = tlvReader.GetDataPtr(peer_verifier));
     739             : 
     740           5 :     VerifyOrExit(peer_verifier_len == kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     741             : 
     742           5 :     SuccessOrExit(err = mSpake2p.KeyConfirm(peer_verifier, peer_verifier_len));
     743             : 
     744             :     // Send confirmation to peer that we succeeded so they can start using the session.
     745           5 :     SendStatusReport(mExchangeCtxt, kProtocolCodeSuccess);
     746             : 
     747           5 :     Finish();
     748           5 : exit:
     749             : 
     750           5 :     if (err != CHIP_NO_ERROR)
     751             :     {
     752           0 :         SendStatusReport(mExchangeCtxt, kProtocolCodeInvalidParam);
     753             :     }
     754           5 :     return err;
     755           5 : }
     756             : 
     757           5 : void PASESession::OnSuccessStatusReport()
     758             : {
     759           5 :     Finish();
     760           5 : }
     761             : 
     762           1 : CHIP_ERROR PASESession::OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode)
     763             : {
     764           1 :     CHIP_ERROR err = CHIP_NO_ERROR;
     765           1 :     switch (protocolCode)
     766             :     {
     767           1 :     case kProtocolCodeInvalidParam:
     768           1 :         err = CHIP_ERROR_INVALID_PASE_PARAMETER;
     769           1 :         break;
     770             : 
     771           0 :     default:
     772           0 :         err = CHIP_ERROR_INTERNAL;
     773           0 :         break;
     774             :     };
     775           1 :     ChipLogError(SecureChannel, "Received error (protocol code %d) during PASE process: %" CHIP_ERROR_FORMAT, protocolCode,
     776             :                  err.Format());
     777           1 :     return err;
     778             : }
     779             : 
     780          35 : CHIP_ERROR PASESession::ValidateReceivedMessage(ExchangeContext * exchange, const PayloadHeader & payloadHeader,
     781             :                                                 const System::PacketBufferHandle & msg)
     782             : {
     783          35 :     VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     784             : 
     785             :     // mExchangeCtxt can be nullptr if this is the first message (PBKDFParamRequest) received by PASESession
     786             :     // via UnsolicitedMessageHandler. The exchange context is allocated by exchange manager and provided
     787             :     // to the handler (PASESession object).
     788          35 :     if (mExchangeCtxt != nullptr)
     789             :     {
     790          29 :         if (mExchangeCtxt != exchange)
     791             :         {
     792           0 :             ReturnErrorOnFailure(CHIP_ERROR_INVALID_ARGUMENT);
     793             :         }
     794             :     }
     795             :     else
     796             :     {
     797           6 :         mExchangeCtxt = exchange;
     798             :     }
     799             : 
     800          35 :     if (!mExchangeCtxt->GetSessionHandle()->IsUnauthenticatedSession())
     801             :     {
     802           0 :         ChipLogError(SecureChannel, "PASESession received PBKDFParamRequest over encrypted session.  Ignoring.");
     803           0 :         return CHIP_ERROR_INCORRECT_STATE;
     804             :     }
     805             : 
     806          35 :     mExchangeCtxt->UseSuggestedResponseTimeout(kExpectedHighProcessingTime);
     807             : 
     808          35 :     VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     809          35 :     VerifyOrReturnError((mNextExpectedMsg.HasValue() && payloadHeader.HasMessageType(mNextExpectedMsg.Value())) ||
     810             :                             payloadHeader.HasMessageType(MsgType::StatusReport),
     811             :                         CHIP_ERROR_INVALID_MESSAGE_TYPE);
     812             : 
     813          35 :     return CHIP_NO_ERROR;
     814             : }
     815             : 
     816           6 : CHIP_ERROR PASESession::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
     817             : {
     818             :     // Handle messages by myself
     819           6 :     newDelegate = this;
     820           6 :     return CHIP_NO_ERROR;
     821             : }
     822             : 
     823          35 : CHIP_ERROR PASESession::OnMessageReceived(ExchangeContext * exchange, const PayloadHeader & payloadHeader,
     824             :                                           System::PacketBufferHandle && msg)
     825             : {
     826             :     MATTER_TRACE_SCOPE("OnMessageReceived", "PASESession");
     827          35 :     CHIP_ERROR err  = ValidateReceivedMessage(exchange, payloadHeader, msg);
     828          35 :     MsgType msgType = static_cast<MsgType>(payloadHeader.GetMessageType());
     829          35 :     SuccessOrExit(err);
     830             : 
     831             : #if CHIP_CONFIG_SLOW_CRYPTO
     832             :     if (msgType == MsgType::PBKDFParamRequest || msgType == MsgType::PBKDFParamResponse || msgType == MsgType::PASE_Pake1 ||
     833             :         msgType == MsgType::PASE_Pake2 || msgType == MsgType::PASE_Pake3)
     834             :     {
     835             :         SuccessOrExit(err = mExchangeCtxt->FlushAcks());
     836             :     }
     837             : #endif // CHIP_CONFIG_SLOW_CRYPTO
     838             : 
     839          35 :     switch (msgType)
     840             :     {
     841           6 :     case MsgType::PBKDFParamRequest:
     842           6 :         err = HandlePBKDFParamRequest(std::move(msg));
     843           6 :         break;
     844             : 
     845           6 :     case MsgType::PBKDFParamResponse:
     846           6 :         err = HandlePBKDFParamResponse(std::move(msg));
     847           6 :         break;
     848             : 
     849           6 :     case MsgType::PASE_Pake1:
     850           6 :         err = HandleMsg1_and_SendMsg2(std::move(msg));
     851           6 :         break;
     852             : 
     853           6 :     case MsgType::PASE_Pake2:
     854           6 :         err = HandleMsg2_and_SendMsg3(std::move(msg));
     855           6 :         break;
     856             : 
     857           5 :     case MsgType::PASE_Pake3:
     858           5 :         err = HandleMsg3(std::move(msg));
     859           5 :         break;
     860             : 
     861           6 :     case MsgType::StatusReport:
     862           6 :         err =
     863           6 :             HandleStatusReport(std::move(msg), mNextExpectedMsg.HasValue() && (mNextExpectedMsg.Value() == MsgType::StatusReport));
     864           6 :         break;
     865             : 
     866           0 :     default:
     867           0 :         err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
     868           0 :         break;
     869             :     };
     870             : 
     871          35 : exit:
     872             : 
     873             :     // Call delegate to indicate pairing failure
     874          35 :     if (err != CHIP_NO_ERROR)
     875             :     {
     876             :         // Discard the exchange so that Clear() doesn't try closing it.  The
     877             :         // exchange will handle that.
     878           2 :         DiscardExchange();
     879           2 :         Clear();
     880           2 :         ChipLogError(SecureChannel, "Failed during PASE session setup: %" CHIP_ERROR_FORMAT, err.Format());
     881             :         MATTER_TRACE_COUNTER("PASEFail");
     882             :         // Do this last in case the delegate frees us.
     883           2 :         NotifySessionEstablishmentError(err);
     884             :     }
     885          35 :     return err;
     886             : }
     887             : 
     888             : } // namespace chip

Generated by: LCOV version 1.14