Matter SDK Coverage Report
Current view: top level - protocols/secure_channel - PASESession.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 93.1 % 451 420
Test Date: 2025-01-17 19:00:11 Functions: 92.0 % 25 23

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

Generated by: LCOV version 2.0-1