LCOV - code coverage report
Current view: top level - controller - CHIPDeviceController.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 1520 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 106 0.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2022 Project CHIP Authors
       4             :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5             :  *    All rights reserved.
       6             :  *
       7             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8             :  *    you may not use this file except in compliance with the License.
       9             :  *    You may obtain a copy of the License at
      10             :  *
      11             :  *        http://www.apache.org/licenses/LICENSE-2.0
      12             :  *
      13             :  *    Unless required by applicable law or agreed to in writing, software
      14             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16             :  *    See the License for the specific language governing permissions and
      17             :  *    limitations under the License.
      18             :  */
      19             : 
      20             : /**
      21             :  *    @file
      22             :  *      Implementation of CHIP Device Controller, a common class
      23             :  *      that implements discovery, pairing and provisioning of CHIP
      24             :  *      devices.
      25             :  *
      26             :  */
      27             : 
      28             : #ifndef __STDC_LIMIT_MACROS
      29             : #define __STDC_LIMIT_MACROS
      30             : #endif
      31             : #ifndef __STDC_FORMAT_MACROS
      32             : #define __STDC_FORMAT_MACROS
      33             : #endif
      34             : 
      35             : // module header, comes first
      36             : #include <controller/CHIPDeviceController.h>
      37             : 
      38             : #include <app-common/zap-generated/ids/Attributes.h>
      39             : #include <app-common/zap-generated/ids/Clusters.h>
      40             : 
      41             : #include <app/server/Dnssd.h>
      42             : 
      43             : #include <app/InteractionModelEngine.h>
      44             : #include <app/OperationalSessionSetup.h>
      45             : #include <controller/CurrentFabricRemover.h>
      46             : #include <credentials/CHIPCert.h>
      47             : #include <credentials/DeviceAttestationCredsProvider.h>
      48             : #include <crypto/CHIPCryptoPAL.h>
      49             : #include <lib/core/CHIPCore.h>
      50             : #include <lib/core/CHIPEncoding.h>
      51             : #include <lib/core/CHIPSafeCasts.h>
      52             : #include <lib/core/ErrorStr.h>
      53             : #include <lib/core/NodeId.h>
      54             : #include <lib/support/Base64.h>
      55             : #include <lib/support/CHIPArgParser.hpp>
      56             : #include <lib/support/CHIPMem.h>
      57             : #include <lib/support/CodeUtils.h>
      58             : #include <lib/support/PersistentStorageMacros.h>
      59             : #include <lib/support/SafeInt.h>
      60             : #include <lib/support/ScopedBuffer.h>
      61             : #include <lib/support/ThreadOperationalDataset.h>
      62             : #include <lib/support/TimeUtils.h>
      63             : #include <lib/support/logging/CHIPLogging.h>
      64             : #include <messaging/ExchangeContext.h>
      65             : #include <platform/LockTracker.h>
      66             : #include <protocols/secure_channel/MessageCounterManager.h>
      67             : #include <setup_payload/QRCodeSetupPayloadParser.h>
      68             : #include <tracing/macros.h>
      69             : 
      70             : #if CONFIG_NETWORK_LAYER_BLE
      71             : #include <ble/BleLayer.h>
      72             : #include <transport/raw/BLE.h>
      73             : #endif
      74             : 
      75             : #include <errno.h>
      76             : #include <inttypes.h>
      77             : #include <memory>
      78             : #include <stdint.h>
      79             : #include <stdlib.h>
      80             : #include <time.h>
      81             : 
      82             : using namespace chip::Inet;
      83             : using namespace chip::System;
      84             : using namespace chip::Transport;
      85             : using namespace chip::Credentials;
      86             : using namespace chip::app::Clusters;
      87             : 
      88             : namespace chip {
      89             : namespace Controller {
      90             : 
      91             : using namespace chip::Encoding;
      92             : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
      93             : using namespace chip::Protocols::UserDirectedCommissioning;
      94             : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
      95             : 
      96           0 : DeviceController::DeviceController()
      97             : {
      98           0 :     mState = State::NotInitialized;
      99           0 : }
     100             : 
     101           0 : CHIP_ERROR DeviceController::Init(ControllerInitParams params)
     102             : {
     103           0 :     assertChipStackLockedByCurrentThread();
     104             : 
     105           0 :     VerifyOrReturnError(mState == State::NotInitialized, CHIP_ERROR_INCORRECT_STATE);
     106           0 :     VerifyOrReturnError(params.systemState != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     107             : 
     108           0 :     VerifyOrReturnError(params.systemState->SystemLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     109           0 :     VerifyOrReturnError(params.systemState->UDPEndPointManager() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     110             : 
     111             : #if CONFIG_NETWORK_LAYER_BLE
     112           0 :     VerifyOrReturnError(params.systemState->BleLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     113             : #endif
     114             : 
     115           0 :     VerifyOrReturnError(params.systemState->TransportMgr() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     116             : 
     117           0 :     ReturnErrorOnFailure(mDNSResolver.Init(params.systemState->UDPEndPointManager()));
     118           0 :     mDNSResolver.SetCommissioningDelegate(this);
     119           0 :     RegisterDeviceDiscoveryDelegate(params.deviceDiscoveryDelegate);
     120             : 
     121           0 :     VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     122           0 :     mOperationalCredentialsDelegate = params.operationalCredentialsDelegate;
     123             : 
     124           0 :     mVendorId = params.controllerVendorId;
     125           0 :     if (params.operationalKeypair != nullptr || !params.controllerNOC.empty() || !params.controllerRCAC.empty())
     126             :     {
     127           0 :         ReturnErrorOnFailure(InitControllerNOCChain(params));
     128             :     }
     129             : 
     130           0 :     mSystemState = params.systemState->Retain();
     131           0 :     mState       = State::Initialized;
     132             : 
     133           0 :     mRemoveFromFabricTableOnShutdown = params.removeFromFabricTableOnShutdown;
     134             : 
     135           0 :     if (GetFabricIndex() != kUndefinedFabricIndex)
     136             :     {
     137           0 :         ChipLogProgress(Controller,
     138             :                         "Joined the fabric at index %d. Fabric ID is 0x" ChipLogFormatX64
     139             :                         " (Compressed Fabric ID: " ChipLogFormatX64 ")",
     140             :                         GetFabricIndex(), ChipLogValueX64(GetFabricId()), ChipLogValueX64(GetCompressedFabricId()));
     141             :     }
     142             : 
     143           0 :     return CHIP_NO_ERROR;
     144             : }
     145             : 
     146           0 : CHIP_ERROR DeviceController::InitControllerNOCChain(const ControllerInitParams & params)
     147             : {
     148           0 :     FabricInfo newFabric;
     149           0 :     constexpr uint32_t chipCertAllocatedLen = kMaxCHIPCertLength;
     150           0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> rcacBuf;
     151           0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
     152           0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> nocBuf;
     153           0 :     Credentials::P256PublicKeySpan rootPublicKeySpan;
     154             :     FabricId fabricId;
     155             :     NodeId nodeId;
     156           0 :     bool hasExternallyOwnedKeypair                   = false;
     157           0 :     Crypto::P256Keypair * externalOperationalKeypair = nullptr;
     158           0 :     VendorId newFabricVendorId                       = params.controllerVendorId;
     159             : 
     160             :     // There are three possibilities here in terms of what happens with our
     161             :     // operational key:
     162             :     // 1) We have an externally owned operational keypair.
     163             :     // 2) We have an operational keypair that the fabric table should clone via
     164             :     //    serialize/deserialize.
     165             :     // 3) We have no keypair at all, and the fabric table has been initialized
     166             :     //    with a key store.
     167           0 :     if (params.operationalKeypair != nullptr)
     168             :     {
     169           0 :         hasExternallyOwnedKeypair  = params.hasExternallyOwnedOperationalKeypair;
     170           0 :         externalOperationalKeypair = params.operationalKeypair;
     171             :     }
     172             : 
     173           0 :     ReturnErrorCodeIf(!rcacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
     174           0 :     ReturnErrorCodeIf(!icacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
     175           0 :     ReturnErrorCodeIf(!nocBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
     176             : 
     177           0 :     MutableByteSpan rcacSpan(rcacBuf.Get(), chipCertAllocatedLen);
     178             : 
     179           0 :     ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerRCAC, rcacSpan));
     180           0 :     ReturnErrorOnFailure(Credentials::ExtractPublicKeyFromChipCert(rcacSpan, rootPublicKeySpan));
     181           0 :     Crypto::P256PublicKey rootPublicKey{ rootPublicKeySpan };
     182             : 
     183           0 :     MutableByteSpan icacSpan;
     184           0 :     if (params.controllerICAC.empty())
     185             :     {
     186           0 :         ChipLogProgress(Controller, "Intermediate CA is not needed");
     187             :     }
     188             :     else
     189             :     {
     190           0 :         icacSpan = MutableByteSpan(icacBuf.Get(), chipCertAllocatedLen);
     191           0 :         ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerICAC, icacSpan));
     192             :     }
     193             : 
     194           0 :     MutableByteSpan nocSpan = MutableByteSpan(nocBuf.Get(), chipCertAllocatedLen);
     195             : 
     196           0 :     ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerNOC, nocSpan));
     197           0 :     ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(nocSpan, &nodeId, &fabricId));
     198             : 
     199           0 :     auto * fabricTable            = params.systemState->Fabrics();
     200           0 :     const FabricInfo * fabricInfo = nullptr;
     201             : 
     202             :     //
     203             :     // When multiple controllers are permitted on the same fabric, we need to find fabrics with
     204             :     // nodeId as an extra discriminant since we can have multiple FabricInfo objects that all
     205             :     // collide on the same fabric. Not doing so may result in a match with an existing FabricInfo
     206             :     // instance that matches the fabric in the provided NOC but is associated with a different NodeId
     207             :     // that is already in use by another active controller instance. That will effectively cause it
     208             :     // to change its identity inadvertently, which is not acceptable.
     209             :     //
     210             :     // TODO: Figure out how to clean up unreclaimed FabricInfos restored from persistent
     211             :     //       storage that are not in use by active DeviceController instances. Also, figure out
     212             :     //       how to reclaim FabricInfo slots when a DeviceController instance is deleted.
     213             :     //
     214           0 :     if (params.permitMultiControllerFabrics)
     215             :     {
     216           0 :         fabricInfo = fabricTable->FindIdentity(rootPublicKey, fabricId, nodeId);
     217             :     }
     218             :     else
     219             :     {
     220           0 :         fabricInfo = fabricTable->FindFabric(rootPublicKey, fabricId);
     221             :     }
     222             : 
     223           0 :     bool fabricFoundInTable = (fabricInfo != nullptr);
     224             : 
     225           0 :     FabricIndex fabricIndex = fabricFoundInTable ? fabricInfo->GetFabricIndex() : kUndefinedFabricIndex;
     226             : 
     227           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     228             : 
     229           0 :     auto advertiseOperational =
     230           0 :         params.enableServerInteractions ? FabricTable::AdvertiseIdentity::Yes : FabricTable::AdvertiseIdentity::No;
     231             : 
     232             :     //
     233             :     // We permit colliding fabrics when multiple controllers are present on the same logical fabric
     234             :     // since each controller is associated with a unique FabricInfo 'identity' object and consequently,
     235             :     // a unique FabricIndex.
     236             :     //
     237             :     // This sets a flag that will be cleared automatically when the fabric is committed/reverted later
     238             :     // in this function.
     239             :     //
     240           0 :     if (params.permitMultiControllerFabrics)
     241             :     {
     242           0 :         fabricTable->PermitCollidingFabrics();
     243             :     }
     244             : 
     245             :     // We have 4 cases to handle legacy usage of direct operational key injection
     246           0 :     if (externalOperationalKeypair)
     247             :     {
     248             :         // Cases 1 and 2: Injected operational keys
     249             : 
     250             :         // CASE 1: Fabric update with injected key
     251           0 :         if (fabricFoundInTable)
     252             :         {
     253           0 :             err = fabricTable->UpdatePendingFabricWithProvidedOpKey(fabricIndex, nocSpan, icacSpan, externalOperationalKeypair,
     254             :                                                                     hasExternallyOwnedKeypair, advertiseOperational);
     255             :         }
     256             :         else
     257             :         // CASE 2: New fabric with injected key
     258             :         {
     259           0 :             err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
     260           0 :             if (err == CHIP_NO_ERROR)
     261             :             {
     262           0 :                 err = fabricTable->AddNewPendingFabricWithProvidedOpKey(nocSpan, icacSpan, newFabricVendorId,
     263             :                                                                         externalOperationalKeypair, hasExternallyOwnedKeypair,
     264             :                                                                         &fabricIndex, advertiseOperational);
     265             :             }
     266             :         }
     267             :     }
     268             :     else
     269             :     {
     270             :         // Cases 3 and 4: OperationalKeystore has the keys
     271             : 
     272             :         // CASE 3: Fabric update with operational keystore
     273           0 :         if (fabricFoundInTable)
     274             :         {
     275           0 :             VerifyOrReturnError(fabricTable->HasOperationalKeyForFabric(fabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
     276             : 
     277           0 :             err = fabricTable->UpdatePendingFabricWithOperationalKeystore(fabricIndex, nocSpan, icacSpan, advertiseOperational);
     278             :         }
     279             :         else
     280             :         // CASE 4: New fabric with operational keystore
     281             :         {
     282           0 :             err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
     283           0 :             if (err == CHIP_NO_ERROR)
     284             :             {
     285           0 :                 err = fabricTable->AddNewPendingFabricWithOperationalKeystore(nocSpan, icacSpan, newFabricVendorId, &fabricIndex,
     286             :                                                                               advertiseOperational);
     287             :             }
     288             : 
     289           0 :             if (err == CHIP_NO_ERROR)
     290             :             {
     291             :                 // Now that we know our planned fabric index, verify that the
     292             :                 // keystore has a key for it.
     293           0 :                 if (!fabricTable->HasOperationalKeyForFabric(fabricIndex))
     294             :                 {
     295           0 :                     err = CHIP_ERROR_KEY_NOT_FOUND;
     296             :                 }
     297             :             }
     298             :         }
     299             :     }
     300             : 
     301             :     // Commit after setup, error-out on failure.
     302           0 :     if (err == CHIP_NO_ERROR)
     303             :     {
     304             :         // No need to revert on error: CommitPendingFabricData reverts internally on *any* error.
     305           0 :         err = fabricTable->CommitPendingFabricData();
     306             :     }
     307             :     else
     308             :     {
     309           0 :         fabricTable->RevertPendingFabricData();
     310             :     }
     311             : 
     312           0 :     ReturnErrorOnFailure(err);
     313           0 :     VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
     314             : 
     315           0 :     mFabricIndex = fabricIndex;
     316             : 
     317           0 :     return CHIP_NO_ERROR;
     318           0 : }
     319             : 
     320           0 : void DeviceController::Shutdown()
     321             : {
     322           0 :     assertChipStackLockedByCurrentThread();
     323             : 
     324           0 :     VerifyOrReturn(mState != State::NotInitialized);
     325             : 
     326           0 :     ChipLogDetail(Controller, "Shutting down the controller");
     327             : 
     328           0 :     mState = State::NotInitialized;
     329             : 
     330           0 :     if (mFabricIndex != kUndefinedFabricIndex)
     331             :     {
     332             :         // Shut down any subscription clients for this fabric.
     333           0 :         app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(mFabricIndex);
     334             : 
     335             :         // Shut down any ongoing CASE session activity we have.  We're going to
     336             :         // assume that all sessions for our fabric belong to us here.
     337           0 :         mSystemState->CASESessionMgr()->ReleaseSessionsForFabric(mFabricIndex);
     338             : 
     339             :         // TODO: The CASE session manager does not shut down existing CASE
     340             :         // sessions.  It just shuts down any ongoing CASE session establishment
     341             :         // we're in the middle of as initiator.  Maybe it should shut down
     342             :         // existing sessions too?
     343           0 :         mSystemState->SessionMgr()->ExpireAllSessionsForFabric(mFabricIndex);
     344             : 
     345           0 :         if (mRemoveFromFabricTableOnShutdown)
     346             :         {
     347           0 :             FabricTable * fabricTable = mSystemState->Fabrics();
     348           0 :             if (fabricTable != nullptr)
     349             :             {
     350           0 :                 fabricTable->Forget(mFabricIndex);
     351             :             }
     352             :         }
     353             :     }
     354             : 
     355           0 :     mSystemState->Release();
     356           0 :     mSystemState = nullptr;
     357             : 
     358           0 :     mDNSResolver.Shutdown();
     359           0 :     mDeviceDiscoveryDelegate = nullptr;
     360             : }
     361             : 
     362           0 : CHIP_ERROR DeviceController::GetPeerAddressAndPort(NodeId peerId, Inet::IPAddress & addr, uint16_t & port)
     363             : {
     364           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
     365           0 :     Transport::PeerAddress peerAddr;
     366           0 :     ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(peerId), peerAddr));
     367           0 :     addr = peerAddr.GetIPAddress();
     368           0 :     port = peerAddr.GetPort();
     369           0 :     return CHIP_NO_ERROR;
     370             : }
     371             : 
     372           0 : CHIP_ERROR DeviceController::GetPeerAddress(NodeId nodeId, Transport::PeerAddress & addr)
     373             : {
     374           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
     375           0 :     ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(nodeId), addr));
     376             : 
     377           0 :     return CHIP_NO_ERROR;
     378             : }
     379             : 
     380           0 : CHIP_ERROR DeviceController::ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt,
     381             :                                                  Spake2pVerifier & outVerifier)
     382             : {
     383           0 :     ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(outVerifier, iterations, salt, /* useRandomPIN= */ false, setupPincode));
     384             : 
     385           0 :     return CHIP_NO_ERROR;
     386             : }
     387             : 
     388           0 : ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams()
     389             : {
     390             :     return ControllerDeviceInitParams{
     391           0 :         .sessionManager = mSystemState->SessionMgr(),
     392           0 :         .exchangeMgr    = mSystemState->ExchangeMgr(),
     393           0 :     };
     394             : }
     395             : 
     396           0 : DeviceCommissioner::DeviceCommissioner() :
     397           0 :     mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this),
     398             : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
     399           0 :     mOnDeviceConnectionRetryCallback(OnDeviceConnectionRetryFn, this),
     400             : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
     401           0 :     mDeviceAttestationInformationVerificationCallback(OnDeviceAttestationInformationVerification, this),
     402           0 :     mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this)
     403             : {
     404           0 :     mPairingDelegate           = nullptr;
     405           0 :     mDeviceBeingCommissioned   = nullptr;
     406           0 :     mDeviceInPASEEstablishment = nullptr;
     407           0 : }
     408             : 
     409           0 : CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params)
     410             : {
     411           0 :     ReturnErrorOnFailure(DeviceController::Init(params));
     412             : 
     413           0 :     mPairingDelegate = params.pairingDelegate;
     414             : 
     415             :     // Configure device attestation validation
     416           0 :     mDeviceAttestationVerifier = params.deviceAttestationVerifier;
     417           0 :     if (mDeviceAttestationVerifier == nullptr)
     418             :     {
     419           0 :         mDeviceAttestationVerifier = Credentials::GetDeviceAttestationVerifier();
     420           0 :         if (mDeviceAttestationVerifier == nullptr)
     421             :         {
     422           0 :             ChipLogError(Controller,
     423             :                          "Missing DeviceAttestationVerifier configuration at DeviceCommissioner init and none set with "
     424             :                          "Credentials::SetDeviceAttestationVerifier()!");
     425           0 :             return CHIP_ERROR_INVALID_ARGUMENT;
     426             :         }
     427             : 
     428             :         // We fell back on a default from singleton accessor.
     429           0 :         ChipLogProgress(Controller,
     430             :                         "*** Missing DeviceAttestationVerifier configuration at DeviceCommissioner init: using global default, "
     431             :                         "consider passing one in CommissionerInitParams.");
     432             :     }
     433             : 
     434           0 :     if (params.defaultCommissioner != nullptr)
     435             :     {
     436           0 :         mDefaultCommissioner = params.defaultCommissioner;
     437             :     }
     438             :     else
     439             :     {
     440           0 :         mDefaultCommissioner = &mAutoCommissioner;
     441             :     }
     442             : 
     443             : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
     444             :     mUdcTransportMgr = chip::Platform::New<UdcTransportMgr>();
     445             :     ReturnErrorOnFailure(mUdcTransportMgr->Init(Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
     446             :                                                     .SetAddressType(Inet::IPAddressType::kIPv6)
     447             :                                                     .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
     448             : #if INET_CONFIG_ENABLE_IPV4
     449             :                                                     ,
     450             :                                                 Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
     451             :                                                     .SetAddressType(Inet::IPAddressType::kIPv4)
     452             :                                                     .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
     453             : #endif // INET_CONFIG_ENABLE_IPV4
     454             :                                                     ));
     455             : 
     456             :     mUdcServer = chip::Platform::New<UserDirectedCommissioningServer>();
     457             :     mUdcTransportMgr->SetSessionManager(mUdcServer);
     458             :     mUdcServer->SetTransportManager(mUdcTransportMgr);
     459             : 
     460             :     mUdcServer->SetInstanceNameResolver(this);
     461             : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
     462             : 
     463           0 :     mSetUpCodePairer.SetSystemLayer(mSystemState->SystemLayer());
     464             : #if CONFIG_NETWORK_LAYER_BLE
     465           0 :     mSetUpCodePairer.SetBleLayer(mSystemState->BleLayer());
     466             : #endif // CONFIG_NETWORK_LAYER_BLE
     467             : 
     468           0 :     return CHIP_NO_ERROR;
     469             : }
     470             : 
     471           0 : void DeviceCommissioner::Shutdown()
     472             : {
     473           0 :     VerifyOrReturn(mState != State::NotInitialized);
     474             : 
     475           0 :     ChipLogDetail(Controller, "Shutting down the commissioner");
     476             : 
     477           0 :     mSetUpCodePairer.StopPairing();
     478             : 
     479             :     // Check to see if pairing in progress before shutting down
     480           0 :     CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
     481           0 :     if (device != nullptr && device->IsSessionSetupInProgress())
     482             :     {
     483           0 :         ChipLogDetail(Controller, "Setup in progress, stopping setup before shutting down");
     484           0 :         OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
     485             :     }
     486             :     // TODO: If we have a commissioning step in progress, is there a way to cancel that callback?
     487             : 
     488             : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
     489             :     if (mUdcTransportMgr != nullptr)
     490             :     {
     491             :         chip::Platform::Delete(mUdcTransportMgr);
     492             :         mUdcTransportMgr = nullptr;
     493             :     }
     494             :     if (mUdcServer != nullptr)
     495             :     {
     496             :         mUdcServer->SetInstanceNameResolver(nullptr);
     497             :         chip::Platform::Delete(mUdcServer);
     498             :         mUdcServer = nullptr;
     499             :     }
     500             : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
     501             : 
     502             :     // Release everything from the commissionee device pool here.
     503             :     // Make sure to use ReleaseCommissioneeDevice so we don't keep dangling
     504             :     // pointers to the device objects.
     505           0 :     mCommissioneeDevicePool.ForEachActiveObject([this](auto * commissioneeDevice) {
     506           0 :         ReleaseCommissioneeDevice(commissioneeDevice);
     507           0 :         return Loop::Continue;
     508             :     });
     509             : 
     510           0 :     DeviceController::Shutdown();
     511             : }
     512             : 
     513           0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(NodeId id)
     514             : {
     515             :     MATTER_TRACE_SCOPE("FindCommissioneeDevice", "DeviceCommissioner");
     516           0 :     CommissioneeDeviceProxy * foundDevice = nullptr;
     517           0 :     mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
     518           0 :         if (deviceProxy->GetDeviceId() == id)
     519             :         {
     520           0 :             foundDevice = deviceProxy;
     521           0 :             return Loop::Break;
     522             :         }
     523           0 :         return Loop::Continue;
     524             :     });
     525             : 
     526           0 :     return foundDevice;
     527             : }
     528             : 
     529           0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(const Transport::PeerAddress & peerAddress)
     530             : {
     531           0 :     CommissioneeDeviceProxy * foundDevice = nullptr;
     532           0 :     mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
     533           0 :         if (deviceProxy->GetPeerAddress() == peerAddress)
     534             :         {
     535           0 :             foundDevice = deviceProxy;
     536           0 :             return Loop::Break;
     537             :         }
     538           0 :         return Loop::Continue;
     539             :     });
     540             : 
     541           0 :     return foundDevice;
     542             : }
     543             : 
     544           0 : void DeviceCommissioner::ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device)
     545             : {
     546             : #if CONFIG_NETWORK_LAYER_BLE
     547           0 :     if (mSystemState->BleLayer() != nullptr && device->GetDeviceTransportType() == Transport::Type::kBle)
     548             :     {
     549             :         // We only support one BLE connection, so if this is BLE, close it
     550           0 :         ChipLogProgress(Discovery, "Closing all BLE connections");
     551           0 :         mSystemState->BleLayer()->CloseAllBleConnections();
     552             :     }
     553             : #endif
     554             :     // Make sure that there will be no dangling pointer
     555           0 :     if (mDeviceInPASEEstablishment == device)
     556             :     {
     557           0 :         mDeviceInPASEEstablishment = nullptr;
     558             :     }
     559           0 :     if (mDeviceBeingCommissioned == device)
     560             :     {
     561           0 :         mDeviceBeingCommissioned = nullptr;
     562             :     }
     563             : 
     564             :     // Release the commissionee device after we have nulled out our pointers,
     565             :     // because that can call back in to us with error notifications as the
     566             :     // session is released.
     567           0 :     mCommissioneeDevicePool.ReleaseObject(device);
     568           0 : }
     569             : 
     570           0 : CHIP_ERROR DeviceCommissioner::GetDeviceBeingCommissioned(NodeId deviceId, CommissioneeDeviceProxy ** out_device)
     571             : {
     572           0 :     VerifyOrReturnError(out_device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     573           0 :     CommissioneeDeviceProxy * device = FindCommissioneeDevice(deviceId);
     574             : 
     575           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     576             : 
     577           0 :     *out_device = device;
     578             : 
     579           0 :     return CHIP_NO_ERROR;
     580             : }
     581             : 
     582           0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, const CommissioningParameters & params,
     583             :                                           DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
     584             : {
     585             :     MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
     586             : 
     587           0 :     if (mDefaultCommissioner == nullptr)
     588             :     {
     589           0 :         ChipLogError(Controller, "No default commissioner is specified");
     590           0 :         return CHIP_ERROR_INCORRECT_STATE;
     591             :     }
     592           0 :     ReturnErrorOnFailure(mDefaultCommissioner->SetCommissioningParameters(params));
     593             : 
     594           0 :     return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
     595           0 :                                        resolutionData);
     596             : }
     597             : 
     598           0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
     599             :                                           Optional<Dnssd::CommonResolutionData> resolutionData)
     600             : {
     601             :     MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
     602           0 :     return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
     603           0 :                                        resolutionData);
     604             : }
     605             : 
     606           0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params)
     607             : {
     608             :     MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
     609           0 :     ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, params));
     610           0 :     return Commission(remoteDeviceId);
     611             : }
     612             : 
     613           0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams,
     614             :                                           CommissioningParameters & commissioningParams)
     615             : {
     616             :     MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
     617           0 :     ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, rendezvousParams));
     618           0 :     return Commission(remoteDeviceId, commissioningParams);
     619             : }
     620             : 
     621           0 : CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
     622             :                                                        Optional<Dnssd::CommonResolutionData> resolutionData)
     623             : {
     624             :     MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
     625           0 :     return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kPaseOnly, discoveryType,
     626           0 :                                        resolutionData);
     627             : }
     628             : 
     629           0 : CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, RendezvousParameters & params)
     630             : {
     631             :     MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
     632           0 :     CHIP_ERROR err                     = CHIP_NO_ERROR;
     633           0 :     CommissioneeDeviceProxy * device   = nullptr;
     634           0 :     CommissioneeDeviceProxy * current  = nullptr;
     635           0 :     Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
     636             : 
     637           0 :     Messaging::ExchangeContext * exchangeCtxt = nullptr;
     638           0 :     Optional<SessionHandle> session;
     639             : 
     640           0 :     VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
     641           0 :     VerifyOrExit(mDeviceInPASEEstablishment == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
     642             : 
     643             :     // TODO(#13940): We need to specify the peer address for BLE transport in bindings.
     644           0 :     if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle ||
     645           0 :         params.GetPeerAddress().GetTransportType() == Transport::Type::kUndefined)
     646             :     {
     647             : #if CONFIG_NETWORK_LAYER_BLE
     648             : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     649             :         ConnectBleTransportToSelf();
     650             : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
     651           0 :         if (!params.HasBleLayer())
     652             :         {
     653           0 :             params.SetPeerAddress(Transport::PeerAddress::BLE());
     654             :         }
     655           0 :         peerAddress = Transport::PeerAddress::BLE();
     656             : #endif // CONFIG_NETWORK_LAYER_BLE
     657             :     }
     658           0 :     else if (params.GetPeerAddress().GetTransportType() == Transport::Type::kTcp ||
     659           0 :              params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
     660             :     {
     661           0 :         peerAddress = Transport::PeerAddress::UDP(params.GetPeerAddress().GetIPAddress(), params.GetPeerAddress().GetPort(),
     662           0 :                                                   params.GetPeerAddress().GetInterface());
     663             :     }
     664             : 
     665           0 :     current = FindCommissioneeDevice(peerAddress);
     666           0 :     if (current != nullptr)
     667             :     {
     668           0 :         if (current->GetDeviceId() == remoteDeviceId)
     669             :         {
     670             :             // We might be able to just reuse its connection if it has one or is
     671             :             // working on one.
     672           0 :             if (current->IsSecureConnected())
     673             :             {
     674           0 :                 if (mPairingDelegate)
     675             :                 {
     676             :                     // We already have an open secure session to this device, call the callback immediately and early return.
     677           0 :                     mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR);
     678             :                 }
     679           0 :                 return CHIP_NO_ERROR;
     680             :             }
     681           0 :             if (current->IsSessionSetupInProgress())
     682             :             {
     683             :                 // We're not connected yet, but we're in the process of connecting. Pairing delegate will get a callback when
     684             :                 // connection completes
     685           0 :                 return CHIP_NO_ERROR;
     686             :             }
     687             :         }
     688             : 
     689             :         // Either the consumer wants to assign a different device id to this
     690             :         // peer address now (so we can't reuse the commissionee device we have
     691             :         // already) or something has gone strange. Delete the old device, try
     692             :         // again.
     693           0 :         ChipLogError(Controller, "Found unconnected device, removing");
     694           0 :         ReleaseCommissioneeDevice(current);
     695             :     }
     696             : 
     697           0 :     device = mCommissioneeDevicePool.CreateObject();
     698           0 :     VerifyOrExit(device != nullptr, err = CHIP_ERROR_NO_MEMORY);
     699             : 
     700           0 :     mDeviceInPASEEstablishment = device;
     701           0 :     device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress);
     702           0 :     device->UpdateDeviceData(params.GetPeerAddress(), params.GetMRPConfig());
     703             : 
     704             : #if CONFIG_NETWORK_LAYER_BLE
     705           0 :     if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle)
     706             :     {
     707           0 :         if (params.HasConnectionObject())
     708             :         {
     709           0 :             SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetConnectionObject()));
     710             :         }
     711           0 :         else if (params.HasDiscoveredObject())
     712             :         {
     713             :             // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
     714             :             // for later.
     715           0 :             mRendezvousParametersForDeviceDiscoveredOverBle = params;
     716           0 :             SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetDiscoveredObject(), this,
     717             :                                                                                    OnDiscoveredDeviceOverBleSuccess,
     718             :                                                                                    OnDiscoveredDeviceOverBleError));
     719           0 :             ExitNow(CHIP_NO_ERROR);
     720             :         }
     721           0 :         else if (params.HasDiscriminator())
     722             :         {
     723             :             // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
     724             :             // for later.
     725           0 :             mRendezvousParametersForDeviceDiscoveredOverBle = params;
     726             : 
     727           0 :             SetupDiscriminator discriminator;
     728           0 :             discriminator.SetLongValue(params.GetDiscriminator());
     729           0 :             SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(
     730             :                               discriminator, this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError));
     731           0 :             ExitNow(CHIP_NO_ERROR);
     732             :         }
     733             :         else
     734             :         {
     735           0 :             ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT);
     736             :         }
     737             :     }
     738             : #endif
     739           0 :     session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), params.GetMRPConfig());
     740           0 :     VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY);
     741             : 
     742             :     // Allocate the exchange immediately before calling PASESession::Pair.
     743             :     //
     744             :     // PASESession::Pair takes ownership of the exchange and will free it on
     745             :     // error, but can only do this if it is actually called.  Allocating the
     746             :     // exchange context right before calling Pair ensures that if allocation
     747             :     // succeeds, PASESession has taken ownership.
     748           0 :     exchangeCtxt = mSystemState->ExchangeMgr()->NewContext(session.Value(), &device->GetPairing());
     749           0 :     VerifyOrExit(exchangeCtxt != nullptr, err = CHIP_ERROR_INTERNAL);
     750             : 
     751           0 :     err = device->GetPairing().Pair(*mSystemState->SessionMgr(), params.GetSetupPINCode(), GetLocalMRPConfig(), exchangeCtxt, this);
     752           0 :     SuccessOrExit(err);
     753             : 
     754           0 : exit:
     755           0 :     if (err != CHIP_NO_ERROR)
     756             :     {
     757           0 :         if (device != nullptr)
     758             :         {
     759           0 :             ReleaseCommissioneeDevice(device);
     760             :         }
     761             :     }
     762             : 
     763           0 :     return err;
     764           0 : }
     765             : 
     766             : #if CONFIG_NETWORK_LAYER_BLE
     767           0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
     768             : {
     769           0 :     auto self   = static_cast<DeviceCommissioner *>(appState);
     770           0 :     auto device = self->mDeviceInPASEEstablishment;
     771             : 
     772           0 :     if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
     773             :     {
     774           0 :         auto remoteId = device->GetDeviceId();
     775             : 
     776           0 :         auto params = self->mRendezvousParametersForDeviceDiscoveredOverBle;
     777           0 :         params.SetConnectionObject(connObj);
     778           0 :         self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
     779             : 
     780           0 :         self->ReleaseCommissioneeDevice(device);
     781           0 :         LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params));
     782           0 :     }
     783           0 : }
     784             : 
     785           0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
     786             : {
     787           0 :     auto self   = static_cast<DeviceCommissioner *>(appState);
     788           0 :     auto device = self->mDeviceInPASEEstablishment;
     789             : 
     790           0 :     if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
     791             :     {
     792           0 :         self->ReleaseCommissioneeDevice(device);
     793           0 :         self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
     794             : 
     795             :         // Callback is required when BLE discovery fails, otherwise the caller will always be in a suspended state
     796             :         // A better way to handle it should define a new error code
     797           0 :         if (self->mPairingDelegate != nullptr)
     798             :         {
     799           0 :             self->mPairingDelegate->OnPairingComplete(err);
     800             :         }
     801             :     }
     802           0 : }
     803             : #endif // CONFIG_NETWORK_LAYER_BLE
     804             : 
     805           0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningParameters & params)
     806             : {
     807           0 :     if (mDefaultCommissioner == nullptr)
     808             :     {
     809           0 :         ChipLogError(Controller, "No default commissioner is specified");
     810           0 :         return CHIP_ERROR_INCORRECT_STATE;
     811             :     }
     812           0 :     ReturnErrorOnFailure(mDefaultCommissioner->SetCommissioningParameters(params));
     813           0 :     return Commission(remoteDeviceId);
     814             : }
     815             : 
     816           0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId)
     817             : {
     818             :     MATTER_TRACE_SCOPE("Commission", "DeviceCommissioner");
     819           0 :     CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
     820           0 :     if (device == nullptr || (!device->IsSecureConnected() && !device->IsSessionSetupInProgress()))
     821             :     {
     822           0 :         ChipLogError(Controller, "Invalid device for commissioning " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
     823           0 :         return CHIP_ERROR_INCORRECT_STATE;
     824             :     }
     825           0 :     if (!device->IsSecureConnected() && device != mDeviceInPASEEstablishment)
     826             :     {
     827             :         // We should not end up in this state because we won't attempt to establish more than one connection at a time.
     828           0 :         ChipLogError(Controller, "Device is not connected and not being paired " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
     829           0 :         return CHIP_ERROR_INCORRECT_STATE;
     830             :     }
     831             : 
     832           0 :     if (mCommissioningStage != CommissioningStage::kSecurePairing)
     833             :     {
     834           0 :         ChipLogError(Controller, "Commissioning already in progress - not restarting");
     835           0 :         return CHIP_ERROR_INCORRECT_STATE;
     836             :     }
     837             : 
     838           0 :     if (mDefaultCommissioner == nullptr)
     839             :     {
     840           0 :         ChipLogError(Controller, "No default commissioner is specified");
     841           0 :         return CHIP_ERROR_INCORRECT_STATE;
     842             :     }
     843             : 
     844           0 :     ChipLogProgress(Controller, "Commission called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
     845             : 
     846           0 :     mDefaultCommissioner->SetOperationalCredentialsDelegate(mOperationalCredentialsDelegate);
     847           0 :     if (device->IsSecureConnected())
     848             :     {
     849           0 :         mDefaultCommissioner->StartCommissioning(this, device);
     850             :     }
     851             :     else
     852             :     {
     853           0 :         mRunCommissioningAfterConnection = true;
     854             :     }
     855           0 :     return CHIP_NO_ERROR;
     856             : }
     857             : 
     858             : CHIP_ERROR
     859           0 : DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * device,
     860             :                                                                 Credentials::AttestationVerificationResult attestationResult)
     861             : {
     862             :     MATTER_TRACE_SCOPE("continueCommissioningDevice", "DeviceCommissioner");
     863           0 :     if (device == nullptr || device != mDeviceBeingCommissioned)
     864             :     {
     865           0 :         ChipLogError(Controller, "Invalid device for commissioning %p", device);
     866           0 :         return CHIP_ERROR_INCORRECT_STATE;
     867             :     }
     868           0 :     CommissioneeDeviceProxy * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
     869           0 :     if (commissioneeDevice == nullptr)
     870             :     {
     871           0 :         ChipLogError(Controller, "Couldn't find commissionee device");
     872           0 :         return CHIP_ERROR_INCORRECT_STATE;
     873             :     }
     874           0 :     if (!commissioneeDevice->IsSecureConnected() || commissioneeDevice != mDeviceBeingCommissioned)
     875             :     {
     876           0 :         ChipLogError(Controller, "Invalid device for commissioning after attestation failure: 0x" ChipLogFormatX64,
     877             :                      ChipLogValueX64(commissioneeDevice->GetDeviceId()));
     878           0 :         return CHIP_ERROR_INCORRECT_STATE;
     879             :     }
     880             : 
     881           0 :     if (mCommissioningStage != CommissioningStage::kAttestationVerification)
     882             :     {
     883           0 :         ChipLogError(Controller, "Commissioning is not attestation verification phase");
     884           0 :         return CHIP_ERROR_INCORRECT_STATE;
     885             :     }
     886             : 
     887           0 :     if (mDefaultCommissioner == nullptr)
     888             :     {
     889           0 :         ChipLogError(Controller, "No default commissioner is specified");
     890           0 :         return CHIP_ERROR_INCORRECT_STATE;
     891             :     }
     892             : 
     893           0 :     ChipLogProgress(Controller, "Continuing commissioning after attestation failure for device ID 0x" ChipLogFormatX64,
     894             :                     ChipLogValueX64(commissioneeDevice->GetDeviceId()));
     895             : 
     896           0 :     if (attestationResult != AttestationVerificationResult::kSuccess)
     897             :     {
     898           0 :         ChipLogError(Controller, "Client selected error: %u for failed 'Attestation Information' for device",
     899             :                      to_underlying(attestationResult));
     900             : 
     901           0 :         CommissioningDelegate::CommissioningReport report;
     902           0 :         report.Set<AttestationErrorInfo>(attestationResult);
     903           0 :         CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
     904           0 :     }
     905             :     else
     906             :     {
     907           0 :         ChipLogProgress(Controller, "Overriding attestation failure per client and continuing commissioning");
     908           0 :         CommissioningStageComplete(CHIP_NO_ERROR);
     909             :     }
     910           0 :     return CHIP_NO_ERROR;
     911             : }
     912             : 
     913           0 : CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId)
     914             : {
     915           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
     916           0 :     VerifyOrReturnError(remoteDeviceId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
     917             : 
     918           0 :     ChipLogProgress(Controller, "StopPairing called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
     919             : 
     920             :     // If we're still in the process of discovering the device, just stop the SetUpCodePairer
     921           0 :     if (mSetUpCodePairer.StopPairing(remoteDeviceId))
     922             :     {
     923           0 :         return CHIP_NO_ERROR;
     924             :     }
     925             : 
     926             :     // Otherwise we might be pairing and / or commissioning it.
     927           0 :     CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
     928           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
     929             : 
     930           0 :     if (mDeviceBeingCommissioned == device)
     931             :     {
     932           0 :         CommissioningStageComplete(CHIP_ERROR_CANCELLED);
     933             :     }
     934             :     else
     935             :     {
     936           0 :         ReleaseCommissioneeDevice(device);
     937             :     }
     938           0 :     return CHIP_NO_ERROR;
     939             : }
     940             : 
     941           0 : CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId)
     942             : {
     943             :     MATTER_TRACE_SCOPE("UnpairDevice", "DeviceCommissioner");
     944           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
     945             : 
     946           0 :     return AutoCurrentFabricRemover::RemoveCurrentFabric(this, remoteDeviceId);
     947             : }
     948             : 
     949           0 : void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status)
     950             : {
     951           0 :     if (mDeviceInPASEEstablishment != nullptr)
     952             :     {
     953             :         // Release the commissionee device. For BLE, this is stored,
     954             :         // for IP commissioning, we have taken a reference to the
     955             :         // operational node to send the completion command.
     956           0 :         ReleaseCommissioneeDevice(mDeviceInPASEEstablishment);
     957             : 
     958           0 :         if (mPairingDelegate != nullptr)
     959             :         {
     960           0 :             mPairingDelegate->OnPairingComplete(status);
     961             :         }
     962             :     }
     963           0 : }
     964             : 
     965           0 : void DeviceCommissioner::OnSessionEstablishmentError(CHIP_ERROR err)
     966             : {
     967           0 :     if (mPairingDelegate != nullptr)
     968             :     {
     969           0 :         mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingFailed);
     970             :     }
     971             : 
     972           0 :     RendezvousCleanup(err);
     973           0 : }
     974             : 
     975           0 : void DeviceCommissioner::OnSessionEstablished(const SessionHandle & session)
     976             : {
     977             :     // PASE session established.
     978           0 :     CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
     979             : 
     980             :     // We are in the callback for this pairing. Reset so we can pair another device.
     981           0 :     mDeviceInPASEEstablishment = nullptr;
     982             : 
     983           0 :     VerifyOrReturn(device != nullptr, OnSessionEstablishmentError(CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR));
     984             : 
     985           0 :     CHIP_ERROR err = device->SetConnected(session);
     986           0 :     if (err != CHIP_NO_ERROR)
     987             :     {
     988           0 :         ChipLogError(Controller, "Failed in setting up secure channel: err %s", ErrorStr(err));
     989           0 :         OnSessionEstablishmentError(err);
     990           0 :         return;
     991             :     }
     992             : 
     993           0 :     ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake");
     994             : 
     995           0 :     if (mPairingDelegate != nullptr)
     996             :     {
     997           0 :         mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR);
     998             :     }
     999             : 
    1000           0 :     if (mRunCommissioningAfterConnection)
    1001             :     {
    1002           0 :         mRunCommissioningAfterConnection = false;
    1003           0 :         mDefaultCommissioner->StartCommissioning(this, device);
    1004             :     }
    1005             : }
    1006             : 
    1007           0 : CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * device,
    1008             :                                                                   Credentials::CertificateType certificateType,
    1009             :                                                                   Optional<System::Clock::Timeout> timeout)
    1010             : {
    1011             :     MATTER_TRACE_SCOPE("SendCertificateChainRequestCommand", "DeviceCommissioner");
    1012           0 :     ChipLogDetail(Controller, "Sending Certificate Chain request to %p device", device);
    1013           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1014             : 
    1015           0 :     OperationalCredentials::Commands::CertificateChainRequest::Type request;
    1016           0 :     request.certificateType = static_cast<OperationalCredentials::CertificateChainTypeEnum>(certificateType);
    1017           0 :     return SendCommand(device, request, OnCertificateChainResponse, OnCertificateChainFailureResponse, timeout);
    1018             : }
    1019             : 
    1020           0 : void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ERROR error)
    1021             : {
    1022             :     MATTER_TRACE_SCOPE("OnCertificateChainFailureResponse", "DeviceCommissioner");
    1023           0 :     ChipLogProgress(Controller, "Device failed to receive the Certificate Chain request Response: %s", chip::ErrorStr(error));
    1024           0 :     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
    1025           0 :     commissioner->CommissioningStageComplete(error);
    1026           0 : }
    1027             : 
    1028           0 : void DeviceCommissioner::OnCertificateChainResponse(
    1029             :     void * context, const chip::app::Clusters::OperationalCredentials::Commands::CertificateChainResponse::DecodableType & response)
    1030             : {
    1031             :     MATTER_TRACE_SCOPE("OnCertificateChainResponse", "DeviceCommissioner");
    1032           0 :     ChipLogProgress(Controller, "Received certificate chain from the device");
    1033           0 :     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
    1034             : 
    1035           0 :     CommissioningDelegate::CommissioningReport report;
    1036           0 :     report.Set<RequestedCertificate>(RequestedCertificate(response.certificate));
    1037             : 
    1038           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
    1039           0 : }
    1040             : 
    1041           0 : CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * device, const ByteSpan & attestationNonce,
    1042             :                                                              Optional<System::Clock::Timeout> timeout)
    1043             : {
    1044             :     MATTER_TRACE_SCOPE("SendAttestationRequestCommand", "DeviceCommissioner");
    1045           0 :     ChipLogDetail(Controller, "Sending Attestation request to %p device", device);
    1046           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1047             : 
    1048           0 :     OperationalCredentials::Commands::AttestationRequest::Type request;
    1049           0 :     request.attestationNonce = attestationNonce;
    1050             : 
    1051           0 :     ReturnErrorOnFailure(SendCommand(device, request, OnAttestationResponse, OnAttestationFailureResponse, timeout));
    1052           0 :     ChipLogDetail(Controller, "Sent Attestation request, waiting for the Attestation Information");
    1053           0 :     return CHIP_NO_ERROR;
    1054             : }
    1055             : 
    1056           0 : void DeviceCommissioner::OnAttestationFailureResponse(void * context, CHIP_ERROR error)
    1057             : {
    1058             :     MATTER_TRACE_SCOPE("OnAttestationFailureResponse", "DeviceCommissioner");
    1059           0 :     ChipLogProgress(Controller, "Device failed to receive the Attestation Information Response: %s", chip::ErrorStr(error));
    1060           0 :     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
    1061           0 :     commissioner->CommissioningStageComplete(error);
    1062           0 : }
    1063             : 
    1064           0 : void DeviceCommissioner::OnAttestationResponse(void * context,
    1065             :                                                const OperationalCredentials::Commands::AttestationResponse::DecodableType & data)
    1066             : {
    1067             :     MATTER_TRACE_SCOPE("OnAttestationResponse", "DeviceCommissioner");
    1068           0 :     ChipLogProgress(Controller, "Received Attestation Information from the device");
    1069           0 :     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
    1070             : 
    1071           0 :     CommissioningDelegate::CommissioningReport report;
    1072           0 :     report.Set<AttestationResponse>(AttestationResponse(data.attestationElements, data.attestationSignature));
    1073           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
    1074           0 : }
    1075             : 
    1076           0 : void DeviceCommissioner::OnDeviceAttestationInformationVerification(
    1077             :     void * context, const Credentials::DeviceAttestationVerifier::AttestationInfo & info, AttestationVerificationResult result)
    1078             : {
    1079             :     MATTER_TRACE_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner");
    1080           0 :     DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
    1081             : 
    1082           0 :     if (!commissioner->mDeviceBeingCommissioned)
    1083             :     {
    1084           0 :         ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device");
    1085           0 :         return;
    1086             :     }
    1087             : 
    1088           0 :     auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
    1089           0 :     Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
    1090             : 
    1091           0 :     if (result != AttestationVerificationResult::kSuccess)
    1092             :     {
    1093           0 :         CommissioningDelegate::CommissioningReport report;
    1094           0 :         report.Set<AttestationErrorInfo>(result);
    1095           0 :         if (result == AttestationVerificationResult::kNotImplemented)
    1096             :         {
    1097           0 :             ChipLogError(Controller,
    1098             :                          "Failed in verifying 'Attestation Information' command received from the device due to default "
    1099             :                          "DeviceAttestationVerifier Class not being overridden by a real implementation.");
    1100           0 :             commissioner->CommissioningStageComplete(CHIP_ERROR_NOT_IMPLEMENTED, report);
    1101           0 :             return;
    1102             :         }
    1103             : 
    1104           0 :         ChipLogError(Controller,
    1105             :                      "Failed in verifying 'Attestation Information' command received from the device: err %hu. Look at "
    1106             :                      "AttestationVerificationResult enum to understand the errors",
    1107             :                      static_cast<uint16_t>(result));
    1108             :         // Go look at AttestationVerificationResult enum in src/credentials/attestation_verifier/DeviceAttestationVerifier.h to
    1109             :         // understand the errors.
    1110             : 
    1111             :         // If a device attestation status delegate is installed, delegate handling of failure to the client and let them
    1112             :         // decide on whether to proceed further or not.
    1113           0 :         if (deviceAttestationDelegate)
    1114             :         {
    1115           0 :             commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
    1116             :         }
    1117             :         else
    1118             :         {
    1119           0 :             commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
    1120             :         }
    1121           0 :     }
    1122             :     else
    1123             :     {
    1124           0 :         if (deviceAttestationDelegate && deviceAttestationDelegate->ShouldWaitAfterDeviceAttestation())
    1125             :         {
    1126           0 :             commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
    1127             :         }
    1128             :         else
    1129             :         {
    1130           0 :             ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device.");
    1131           0 :             commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    1132             :         }
    1133             :     }
    1134             : }
    1135             : 
    1136           0 : void DeviceCommissioner::OnArmFailSafeExtendedForDeviceAttestation(
    1137             :     void * context, const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
    1138             : {
    1139             :     // If this function starts using "data", need to fix ExtendArmFailSafeForDeviceAttestation accordingly.
    1140           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1141             : 
    1142           0 :     if (!commissioner->mDeviceBeingCommissioned)
    1143             :     {
    1144           0 :         return;
    1145             :     }
    1146             : 
    1147           0 :     auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
    1148           0 :     Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
    1149           0 :     if (deviceAttestationDelegate)
    1150             :     {
    1151           0 :         ChipLogProgress(Controller, "Device attestation completed, delegating continuation to client");
    1152           0 :         deviceAttestationDelegate->OnDeviceAttestationCompleted(commissioner, commissioner->mDeviceBeingCommissioned,
    1153           0 :                                                                 *commissioner->mAttestationDeviceInfo,
    1154             :                                                                 commissioner->mAttestationResult);
    1155             :     }
    1156             :     else
    1157             :     {
    1158           0 :         ChipLogProgress(Controller, "Device attestation failed and no delegate set, failing commissioning");
    1159           0 :         CommissioningDelegate::CommissioningReport report;
    1160           0 :         report.Set<AttestationErrorInfo>(commissioner->mAttestationResult);
    1161           0 :         commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
    1162           0 :     }
    1163             : }
    1164             : 
    1165           0 : void DeviceCommissioner::OnFailedToExtendedArmFailSafeDeviceAttestation(void * context, CHIP_ERROR error)
    1166             : {
    1167           0 :     ChipLogProgress(Controller, "Failed to extend fail-safe timer to handle attestation failure %s", chip::ErrorStr(error));
    1168           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1169             : 
    1170           0 :     CommissioningDelegate::CommissioningReport report;
    1171           0 :     report.Set<AttestationErrorInfo>(commissioner->mAttestationResult);
    1172           0 :     commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
    1173           0 : }
    1174             : 
    1175           0 : void DeviceCommissioner::OnICDManagementRegisterClientResponse(
    1176             :     void * context, const app::Clusters::IcdManagement::Commands::RegisterClientResponse::DecodableType & data)
    1177             : {
    1178           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1179           0 :     VerifyOrReturn(commissioner != nullptr, ChipLogProgress(Controller, "Command response callback with null context. Ignoring"));
    1180             : 
    1181           0 :     if (commissioner->mCommissioningStage != CommissioningStage::kICDRegistration)
    1182             :     {
    1183           0 :         return;
    1184             :     }
    1185             : 
    1186           0 :     if (commissioner->mDeviceBeingCommissioned == nullptr)
    1187             :     {
    1188           0 :         return;
    1189             :     }
    1190             : 
    1191           0 :     if (commissioner->mPairingDelegate != nullptr)
    1192             :     {
    1193           0 :         commissioner->mPairingDelegate->OnICDRegistrationComplete(commissioner->mDeviceBeingCommissioned->GetDeviceId(),
    1194           0 :                                                                   data.ICDCounter);
    1195             :     }
    1196           0 :     CommissioningDelegate::CommissioningReport report;
    1197           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
    1198           0 : }
    1199             : 
    1200           0 : bool DeviceCommissioner::ExtendArmFailSafe(DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout,
    1201             :                                            Optional<System::Clock::Timeout> commandTimeout, OnExtendFailsafeSuccess onSuccess,
    1202             :                                            OnExtendFailsafeFailure onFailure)
    1203             : {
    1204             :     using namespace System;
    1205             :     using namespace System::Clock;
    1206           0 :     auto now                = SystemClock().GetMonotonicTimestamp();
    1207           0 :     auto newFailSafeTimeout = now + Seconds16(armFailSafeTimeout);
    1208           0 :     if (newFailSafeTimeout < proxy->GetFailSafeExpirationTimestamp())
    1209             :     {
    1210           0 :         ChipLogProgress(
    1211             :             Controller, "Skipping arming failsafe: new time (%u seconds from now) before old time (%u seconds from now)",
    1212             :             armFailSafeTimeout, std::chrono::duration_cast<Seconds16>(proxy->GetFailSafeExpirationTimestamp() - now).count());
    1213           0 :         return false;
    1214             :     }
    1215             : 
    1216           0 :     uint64_t breadcrumb = static_cast<uint64_t>(step);
    1217           0 :     GeneralCommissioning::Commands::ArmFailSafe::Type request;
    1218           0 :     request.expiryLengthSeconds = armFailSafeTimeout;
    1219           0 :     request.breadcrumb          = breadcrumb;
    1220           0 :     ChipLogProgress(Controller, "Arming failsafe (%u seconds)", request.expiryLengthSeconds);
    1221           0 :     CHIP_ERROR err = SendCommand(proxy, request, onSuccess, onFailure, kRootEndpointId, commandTimeout);
    1222           0 :     if (err != CHIP_NO_ERROR)
    1223             :     {
    1224           0 :         onFailure(this, err);
    1225             :     }
    1226             :     else
    1227             :     {
    1228             :         // TODO: Handle the situation when our command ends up erroring out
    1229             :         // asynchronously?
    1230           0 :         proxy->SetFailSafeExpirationTimestamp(newFailSafeTimeout);
    1231             :     }
    1232           0 :     return true;
    1233             : }
    1234             : 
    1235           0 : void DeviceCommissioner::ExtendArmFailSafeForDeviceAttestation(const Credentials::DeviceAttestationVerifier::AttestationInfo & info,
    1236             :                                                                Credentials::AttestationVerificationResult result)
    1237             : {
    1238           0 :     mAttestationResult = result;
    1239             : 
    1240           0 :     auto & params                                                      = mDefaultCommissioner->GetCommissioningParameters();
    1241           0 :     Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
    1242             : 
    1243           0 :     mAttestationDeviceInfo = Platform::MakeUnique<Credentials::DeviceAttestationVerifier::AttestationDeviceInfo>(info);
    1244             : 
    1245           0 :     auto expiryLengthSeconds      = deviceAttestationDelegate->FailSafeExpiryTimeoutSecs();
    1246           0 :     bool waitForFailsafeExtension = expiryLengthSeconds.HasValue();
    1247           0 :     if (waitForFailsafeExtension)
    1248             :     {
    1249           0 :         ChipLogProgress(Controller, "Changing fail-safe timer to %u seconds to handle DA failure", expiryLengthSeconds.Value());
    1250             :         // Per spec, anything we do with the fail-safe armed must not time out
    1251             :         // in less than kMinimumCommissioningStepTimeout.
    1252             :         waitForFailsafeExtension =
    1253           0 :             ExtendArmFailSafe(mDeviceBeingCommissioned, mCommissioningStage, expiryLengthSeconds.Value(),
    1254           0 :                               MakeOptional(kMinimumCommissioningStepTimeout), OnArmFailSafeExtendedForDeviceAttestation,
    1255             :                               OnFailedToExtendedArmFailSafeDeviceAttestation);
    1256             :     }
    1257             :     else
    1258             :     {
    1259           0 :         ChipLogProgress(Controller, "Proceeding without changing fail-safe timer value as delegate has not set it");
    1260             :     }
    1261             : 
    1262           0 :     if (!waitForFailsafeExtension)
    1263             :     {
    1264             :         // Callee does not use data argument.
    1265           0 :         const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType data;
    1266           0 :         OnArmFailSafeExtendedForDeviceAttestation(this, data);
    1267             :     }
    1268           0 : }
    1269             : 
    1270           0 : CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
    1271             : {
    1272             :     MATTER_TRACE_SCOPE("ValidateAttestationInfo", "DeviceCommissioner");
    1273           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
    1274           0 :     VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
    1275             : 
    1276           0 :     mDeviceAttestationVerifier->VerifyAttestationInformation(info, &mDeviceAttestationInformationVerificationCallback);
    1277             : 
    1278             :     // TODO: Validate Firmware Information
    1279             : 
    1280           0 :     return CHIP_NO_ERROR;
    1281             : }
    1282             : 
    1283           0 : CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
    1284             :                                            const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce)
    1285             : {
    1286             :     MATTER_TRACE_SCOPE("ValidateCSR", "DeviceCommissioner");
    1287           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
    1288           0 :     VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
    1289             : 
    1290           0 :     P256PublicKey dacPubkey;
    1291           0 :     ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
    1292             : 
    1293             :     // Retrieve attestation challenge
    1294             :     ByteSpan attestationChallenge =
    1295           0 :         proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
    1296             : 
    1297             :     // The operational CA should also verify this on its end during NOC generation, if end-to-end attestation is desired.
    1298           0 :     return mDeviceAttestationVerifier->VerifyNodeOperationalCSRInformation(NOCSRElements, attestationChallenge,
    1299           0 :                                                                            AttestationSignature, dacPubkey, csrNonce);
    1300           0 : }
    1301             : 
    1302           0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(DeviceProxy * device, const ByteSpan & csrNonce,
    1303             :                                                                                Optional<System::Clock::Timeout> timeout)
    1304             : {
    1305             :     MATTER_TRACE_SCOPE("SendOperationalCertificateSigningRequestCommand", "DeviceCommissioner");
    1306           0 :     ChipLogDetail(Controller, "Sending CSR request to %p device", device);
    1307           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1308             : 
    1309           0 :     OperationalCredentials::Commands::CSRRequest::Type request;
    1310           0 :     request.CSRNonce = csrNonce;
    1311             : 
    1312           0 :     ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateSigningRequest, OnCSRFailureResponse, timeout));
    1313           0 :     ChipLogDetail(Controller, "Sent CSR request, waiting for the CSR");
    1314           0 :     return CHIP_NO_ERROR;
    1315           0 : }
    1316             : 
    1317           0 : void DeviceCommissioner::OnCSRFailureResponse(void * context, CHIP_ERROR error)
    1318             : {
    1319             :     MATTER_TRACE_SCOPE("OnCSRFailureResponse", "DeviceCommissioner");
    1320           0 :     ChipLogProgress(Controller, "Device failed to receive the CSR request Response: %s", chip::ErrorStr(error));
    1321           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1322           0 :     commissioner->CommissioningStageComplete(error);
    1323           0 : }
    1324             : 
    1325           0 : void DeviceCommissioner::OnOperationalCertificateSigningRequest(
    1326             :     void * context, const OperationalCredentials::Commands::CSRResponse::DecodableType & data)
    1327             : {
    1328             :     MATTER_TRACE_SCOPE("OnOperationalCertificateSigningRequest", "DeviceCommissioner");
    1329           0 :     ChipLogProgress(Controller, "Received certificate signing request from the device");
    1330           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1331             : 
    1332           0 :     CommissioningDelegate::CommissioningReport report;
    1333           0 :     report.Set<CSRResponse>(CSRResponse(data.NOCSRElements, data.attestationSignature));
    1334           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
    1335           0 : }
    1336             : 
    1337           0 : void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac,
    1338             :                                                     const ByteSpan & rcac, Optional<IdentityProtectionKeySpan> ipk,
    1339             :                                                     Optional<NodeId> adminSubject)
    1340             : {
    1341             :     MATTER_TRACE_SCOPE("OnDeviceNOCChainGeneration", "DeviceCommissioner");
    1342           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1343             : 
    1344             :     // The placeholder IPK is not satisfactory, but is there to fill the NocChain struct on error. It will still fail.
    1345           0 :     const uint8_t placeHolderIpk[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    1346             :                                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    1347           0 :     if (status == CHIP_NO_ERROR && !ipk.HasValue())
    1348             :     {
    1349           0 :         ChipLogError(Controller, "Did not have an IPK from the OperationalCredentialsIssuer! Cannot commission.");
    1350           0 :         status = CHIP_ERROR_INVALID_ARGUMENT;
    1351             :     }
    1352             : 
    1353           0 :     ChipLogProgress(Controller, "Received callback from the CA for NOC Chain generation. Status %s", ErrorStr(status));
    1354           0 :     if (status == CHIP_NO_ERROR && commissioner->mState != State::Initialized)
    1355             :     {
    1356           0 :         status = CHIP_ERROR_INCORRECT_STATE;
    1357             :     }
    1358           0 :     if (status != CHIP_NO_ERROR)
    1359             :     {
    1360           0 :         ChipLogError(Controller, "Failed in generating device's operational credentials. Error %s", ErrorStr(status));
    1361             :     }
    1362             : 
    1363             :     // TODO - Verify that the generated root cert matches with commissioner's root cert
    1364           0 :     CommissioningDelegate::CommissioningReport report;
    1365           0 :     report.Set<NocChain>(NocChain(noc, icac, rcac, ipk.HasValue() ? ipk.Value() : IdentityProtectionKeySpan(placeHolderIpk),
    1366           0 :                                   adminSubject.HasValue() ? adminSubject.Value() : commissioner->GetNodeId()));
    1367           0 :     commissioner->CommissioningStageComplete(status, report);
    1368           0 : }
    1369             : 
    1370           0 : CHIP_ERROR DeviceCommissioner::IssueNOCChain(const ByteSpan & NOCSRElements, NodeId nodeId,
    1371             :                                              chip::Callback::Callback<OnNOCChainGeneration> * callback)
    1372             : {
    1373             :     MATTER_TRACE_SCOPE("IssueNOCChain", "DeviceCommissioner");
    1374           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
    1375             : 
    1376           0 :     ChipLogProgress(Controller, "Getting certificate chain for the device on fabric idx %u", static_cast<unsigned>(mFabricIndex));
    1377             : 
    1378           0 :     mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(nodeId);
    1379             : 
    1380           0 :     if (mFabricIndex != kUndefinedFabricIndex)
    1381             :     {
    1382           0 :         mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
    1383             :     }
    1384             : 
    1385             :     // Note: we don't have attestationSignature, attestationChallenge, DAC, PAI so we are just providing an empty ByteSpan
    1386             :     // for those arguments.
    1387           0 :     return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(),
    1388           0 :                                                              ByteSpan(), callback);
    1389             : }
    1390             : 
    1391           0 : CHIP_ERROR DeviceCommissioner::ProcessCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
    1392             :                                           const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & pai,
    1393             :                                           const ByteSpan & csrNonce)
    1394             : {
    1395             :     MATTER_TRACE_SCOPE("ProcessOpCSR", "DeviceCommissioner");
    1396           0 :     VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
    1397             : 
    1398           0 :     ChipLogProgress(Controller, "Getting certificate chain for the device from the issuer");
    1399             : 
    1400           0 :     P256PublicKey dacPubkey;
    1401           0 :     ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
    1402             : 
    1403             :     // Retrieve attestation challenge
    1404             :     ByteSpan attestationChallenge =
    1405           0 :         proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
    1406             : 
    1407           0 :     mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(proxy->GetDeviceId());
    1408             : 
    1409           0 :     if (mFabricIndex != kUndefinedFabricIndex)
    1410             :     {
    1411           0 :         mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
    1412             :     }
    1413             : 
    1414           0 :     return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, csrNonce, AttestationSignature, attestationChallenge,
    1415           0 :                                                              dac, pai, &mDeviceNOCChainCallback);
    1416           0 : }
    1417             : 
    1418           0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf,
    1419             :                                                           const Optional<ByteSpan> & icaCertBuf,
    1420             :                                                           const IdentityProtectionKeySpan ipk, const NodeId adminSubject,
    1421             :                                                           Optional<System::Clock::Timeout> timeout)
    1422             : {
    1423             :     MATTER_TRACE_SCOPE("SendOperationalCertificate", "DeviceCommissioner");
    1424             : 
    1425           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1426             : 
    1427           0 :     OperationalCredentials::Commands::AddNOC::Type request;
    1428           0 :     request.NOCValue         = nocCertBuf;
    1429           0 :     request.ICACValue        = icaCertBuf;
    1430           0 :     request.IPKValue         = ipk;
    1431           0 :     request.caseAdminSubject = adminSubject;
    1432           0 :     request.adminVendorId    = mVendorId;
    1433             : 
    1434           0 :     ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateAddResponse, OnAddNOCFailureResponse, timeout));
    1435             : 
    1436           0 :     ChipLogProgress(Controller, "Sent operational certificate to the device");
    1437             : 
    1438           0 :     return CHIP_NO_ERROR;
    1439           0 : }
    1440             : 
    1441           0 : CHIP_ERROR DeviceCommissioner::ConvertFromOperationalCertStatus(OperationalCredentials::NodeOperationalCertStatusEnum err)
    1442             : {
    1443             :     using OperationalCredentials::NodeOperationalCertStatusEnum;
    1444           0 :     switch (err)
    1445             :     {
    1446           0 :     case NodeOperationalCertStatusEnum::kOk:
    1447           0 :         return CHIP_NO_ERROR;
    1448           0 :     case NodeOperationalCertStatusEnum::kInvalidPublicKey:
    1449           0 :         return CHIP_ERROR_INVALID_PUBLIC_KEY;
    1450           0 :     case NodeOperationalCertStatusEnum::kInvalidNodeOpId:
    1451           0 :         return CHIP_ERROR_WRONG_NODE_ID;
    1452           0 :     case NodeOperationalCertStatusEnum::kInvalidNOC:
    1453           0 :         return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
    1454           0 :     case NodeOperationalCertStatusEnum::kMissingCsr:
    1455           0 :         return CHIP_ERROR_INCORRECT_STATE;
    1456           0 :     case NodeOperationalCertStatusEnum::kTableFull:
    1457           0 :         return CHIP_ERROR_NO_MEMORY;
    1458           0 :     case NodeOperationalCertStatusEnum::kInvalidAdminSubject:
    1459           0 :         return CHIP_ERROR_INVALID_ADMIN_SUBJECT;
    1460           0 :     case NodeOperationalCertStatusEnum::kFabricConflict:
    1461           0 :         return CHIP_ERROR_FABRIC_EXISTS;
    1462           0 :     case NodeOperationalCertStatusEnum::kLabelConflict:
    1463           0 :         return CHIP_ERROR_INVALID_ARGUMENT;
    1464           0 :     case NodeOperationalCertStatusEnum::kInvalidFabricIndex:
    1465           0 :         return CHIP_ERROR_INVALID_FABRIC_INDEX;
    1466           0 :     case NodeOperationalCertStatusEnum::kUnknownEnumValue:
    1467             :         // Is this a reasonable value?
    1468           0 :         return CHIP_ERROR_CERT_LOAD_FAILED;
    1469             :     }
    1470             : 
    1471           0 :     return CHIP_ERROR_CERT_LOAD_FAILED;
    1472             : }
    1473             : 
    1474           0 : void DeviceCommissioner::OnAddNOCFailureResponse(void * context, CHIP_ERROR error)
    1475             : {
    1476             :     MATTER_TRACE_SCOPE("OnAddNOCFailureResponse", "DeviceCommissioner");
    1477           0 :     ChipLogProgress(Controller, "Device failed to receive the operational certificate Response: %s", chip::ErrorStr(error));
    1478           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1479           0 :     commissioner->CommissioningStageComplete(error);
    1480           0 : }
    1481             : 
    1482           0 : void DeviceCommissioner::OnOperationalCertificateAddResponse(
    1483             :     void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data)
    1484             : {
    1485             :     MATTER_TRACE_SCOPE("OnOperationalCertificateAddResponse", "DeviceCommissioner");
    1486           0 :     ChipLogProgress(Controller, "Device returned status %d on receiving the NOC", to_underlying(data.statusCode));
    1487           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1488             : 
    1489           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1490             : 
    1491           0 :     VerifyOrExit(commissioner->mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
    1492             : 
    1493           0 :     VerifyOrExit(commissioner->mDeviceBeingCommissioned != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
    1494             : 
    1495           0 :     err = ConvertFromOperationalCertStatus(data.statusCode);
    1496           0 :     SuccessOrExit(err);
    1497             : 
    1498           0 :     err = commissioner->OnOperationalCredentialsProvisioningCompletion(commissioner->mDeviceBeingCommissioned);
    1499             : 
    1500           0 : exit:
    1501           0 :     if (err != CHIP_NO_ERROR)
    1502             :     {
    1503           0 :         ChipLogProgress(Controller, "Add NOC failed with error %s", ErrorStr(err));
    1504           0 :         commissioner->CommissioningStageComplete(err);
    1505             :     }
    1506           0 : }
    1507             : 
    1508           0 : CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, const ByteSpan & rcac,
    1509             :                                                           Optional<System::Clock::Timeout> timeout)
    1510             : {
    1511             :     MATTER_TRACE_SCOPE("SendTrustedRootCertificate", "DeviceCommissioner");
    1512           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1513             : 
    1514           0 :     ChipLogProgress(Controller, "Sending root certificate to the device");
    1515             : 
    1516           0 :     OperationalCredentials::Commands::AddTrustedRootCertificate::Type request;
    1517           0 :     request.rootCACertificate = rcac;
    1518           0 :     ReturnErrorOnFailure(SendCommand(device, request, OnRootCertSuccessResponse, OnRootCertFailureResponse, timeout));
    1519             : 
    1520           0 :     ChipLogProgress(Controller, "Sent root certificate to the device");
    1521             : 
    1522           0 :     return CHIP_NO_ERROR;
    1523             : }
    1524             : 
    1525           0 : void DeviceCommissioner::OnRootCertSuccessResponse(void * context, const chip::app::DataModel::NullObjectType &)
    1526             : {
    1527             :     MATTER_TRACE_SCOPE("OnRootCertSuccessResponse", "DeviceCommissioner");
    1528           0 :     ChipLogProgress(Controller, "Device confirmed that it has received the root certificate");
    1529           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1530           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    1531           0 : }
    1532             : 
    1533           0 : void DeviceCommissioner::OnRootCertFailureResponse(void * context, CHIP_ERROR error)
    1534             : {
    1535             :     MATTER_TRACE_SCOPE("OnRootCertFailureResponse", "DeviceCommissioner");
    1536           0 :     ChipLogProgress(Controller, "Device failed to receive the root certificate Response: %s", chip::ErrorStr(error));
    1537           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1538           0 :     commissioner->CommissioningStageComplete(error);
    1539           0 : }
    1540             : 
    1541           0 : CHIP_ERROR DeviceCommissioner::OnOperationalCredentialsProvisioningCompletion(DeviceProxy * device)
    1542             : {
    1543             :     MATTER_TRACE_SCOPE("OnOperationalCredentialsProvisioningCompletion", "DeviceCommissioner");
    1544           0 :     ChipLogProgress(Controller, "Operational credentials provisioned on device %p", device);
    1545           0 :     VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1546             : 
    1547           0 :     if (mPairingDelegate != nullptr)
    1548             :     {
    1549           0 :         mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingSuccess);
    1550             :     }
    1551           0 :     CommissioningStageComplete(CHIP_NO_ERROR);
    1552             : 
    1553           0 :     return CHIP_NO_ERROR;
    1554             : }
    1555             : 
    1556             : #if CONFIG_NETWORK_LAYER_BLE
    1557             : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
    1558             : void DeviceCommissioner::ConnectBleTransportToSelf()
    1559             : {
    1560             :     Transport::BLEBase & transport = std::get<Transport::BLE<1>>(mSystemState->TransportMgr()->GetTransport().GetTransports());
    1561             :     if (!transport.IsBleLayerTransportSetToSelf())
    1562             :     {
    1563             :         transport.SetBleLayerTransportToSelf();
    1564             :     }
    1565             : }
    1566             : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
    1567             : 
    1568           0 : void DeviceCommissioner::CloseBleConnection()
    1569             : {
    1570             :     // It is fine since we can only commission one device at the same time.
    1571             :     // We should be able to distinguish different BLE connections if we want
    1572             :     // to commission multiple devices at the same time over BLE.
    1573           0 :     mSystemState->BleLayer()->CloseAllBleConnections();
    1574           0 : }
    1575             : #endif
    1576             : 
    1577           0 : CHIP_ERROR DeviceCommissioner::DiscoverCommissionableNodes(Dnssd::DiscoveryFilter filter)
    1578             : {
    1579           0 :     ReturnErrorOnFailure(SetUpNodeDiscovery());
    1580           0 :     return mDNSResolver.DiscoverCommissionableNodes(filter);
    1581             : }
    1582             : 
    1583           0 : CHIP_ERROR DeviceCommissioner::StopCommissionableDiscovery()
    1584             : {
    1585           0 :     return mDNSResolver.StopDiscovery();
    1586             : }
    1587             : 
    1588           0 : const Dnssd::DiscoveredNodeData * DeviceCommissioner::GetDiscoveredDevice(int idx)
    1589             : {
    1590           0 :     return GetDiscoveredNode(idx);
    1591             : }
    1592             : 
    1593             : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
    1594             : 
    1595             : CHIP_ERROR DeviceCommissioner::SetUdcListenPort(uint16_t listenPort)
    1596             : {
    1597             :     if (mState == State::Initialized)
    1598             :     {
    1599             :         return CHIP_ERROR_INCORRECT_STATE;
    1600             :     }
    1601             : 
    1602             :     mUdcListenPort = listenPort;
    1603             :     return CHIP_NO_ERROR;
    1604             : }
    1605             : 
    1606             : void DeviceCommissioner::FindCommissionableNode(char * instanceName)
    1607             : {
    1608             :     Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kInstanceName, instanceName);
    1609             :     DiscoverCommissionableNodes(filter);
    1610             : }
    1611             : 
    1612             : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
    1613             : 
    1614           0 : void DeviceCommissioner::OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData)
    1615             : {
    1616             : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
    1617             :     if (mUdcServer != nullptr)
    1618             :     {
    1619             :         mUdcServer->OnCommissionableNodeFound(nodeData);
    1620             :     }
    1621             : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
    1622           0 :     AbstractDnssdDiscoveryController::OnNodeDiscovered(nodeData);
    1623           0 :     mSetUpCodePairer.NotifyCommissionableDeviceDiscovered(nodeData);
    1624           0 : }
    1625             : 
    1626           0 : void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &)
    1627             : {
    1628           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1629           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    1630           0 : }
    1631             : 
    1632           0 : void OnBasicFailure(void * context, CHIP_ERROR error)
    1633             : {
    1634           0 :     ChipLogProgress(Controller, "Received failure response %s\n", chip::ErrorStr(error));
    1635           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1636           0 :     commissioner->CommissioningStageComplete(error);
    1637           0 : }
    1638             : 
    1639           0 : void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
    1640             : {
    1641           0 :     commissioningCompletionStatus = completionStatus;
    1642             : 
    1643           0 :     if (completionStatus.err == CHIP_NO_ERROR)
    1644             :     {
    1645             : 
    1646           0 :         CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
    1647           0 :         if (commissionee != nullptr)
    1648             :         {
    1649           0 :             ReleaseCommissioneeDevice(commissionee);
    1650             :         }
    1651             :         // Send the callbacks, we're done.
    1652           0 :         CommissioningStageComplete(CHIP_NO_ERROR);
    1653           0 :         SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
    1654             :     }
    1655           0 :     else if (completionStatus.failedStage.HasValue() && completionStatus.failedStage.Value() >= kWiFiNetworkSetup)
    1656             :     {
    1657             :         // If we were already doing network setup, we need to retain the pase session and start again from network setup stage.
    1658             :         // We do not need to reset the failsafe here because we want to keep everything on the device up to this point, so just
    1659             :         // send the completion callbacks.
    1660           0 :         CommissioningStageComplete(CHIP_NO_ERROR);
    1661           0 :         SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
    1662             :     }
    1663             :     else
    1664             :     {
    1665             :         // If we've failed somewhere in the early stages (or we don't have a failedStage specified), we need to start from the
    1666             :         // beginning. However, because some of the commands can only be sent once per arm-failsafe, we also need to force a reset on
    1667             :         // the failsafe so we can start fresh on the next attempt.
    1668           0 :         GeneralCommissioning::Commands::ArmFailSafe::Type request;
    1669           0 :         request.expiryLengthSeconds = 0; // Expire immediately.
    1670           0 :         request.breadcrumb          = 0;
    1671           0 :         ChipLogProgress(Controller, "Expiring failsafe on proxy %p", proxy);
    1672           0 :         mDeviceBeingCommissioned = proxy;
    1673             :         // We actually want to do the same thing on success or failure because we're already in a failure state
    1674           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure,
    1675             :                                      /* timeout = */ NullOptional);
    1676           0 :         if (err != CHIP_NO_ERROR)
    1677             :         {
    1678             :             // We won't get any async callbacks here, so just pretend like the
    1679             :             // command errored out async.
    1680           0 :             ChipLogError(Controller, "Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format());
    1681           0 :             DisarmDone();
    1682           0 :             return;
    1683             :         }
    1684             :     }
    1685             : }
    1686             : 
    1687           0 : void DeviceCommissioner::OnDisarmFailsafe(void * context,
    1688             :                                           const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
    1689             : {
    1690           0 :     ChipLogProgress(Controller, "Failsafe disarmed");
    1691           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1692           0 :     commissioner->DisarmDone();
    1693           0 : }
    1694             : 
    1695           0 : void DeviceCommissioner::OnDisarmFailsafeFailure(void * context, CHIP_ERROR error)
    1696             : {
    1697           0 :     ChipLogProgress(Controller, "Received failure response  when disarming failsafe%s\n", chip::ErrorStr(error));
    1698           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1699           0 :     commissioner->DisarmDone();
    1700           0 : }
    1701             : 
    1702           0 : void DeviceCommissioner::DisarmDone()
    1703             : {
    1704             :     // If someone nulled out our mDeviceBeingCommissioned, there's nothing else
    1705             :     // to do here.
    1706           0 :     VerifyOrReturn(mDeviceBeingCommissioned != nullptr);
    1707             : 
    1708           0 :     NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId();
    1709             :     // At this point, we also want to close off the pase session so we need to re-establish
    1710           0 :     CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
    1711             : 
    1712             :     // Signal completion - this will reset mDeviceBeingCommissioned.
    1713           0 :     CommissioningStageComplete(CHIP_NO_ERROR);
    1714           0 :     SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
    1715             : 
    1716             :     // If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection.
    1717           0 :     if (commissionee != nullptr)
    1718             :     {
    1719           0 :         ReleaseCommissioneeDevice(commissionee);
    1720             :     }
    1721             : }
    1722             : 
    1723           0 : void DeviceCommissioner::SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus)
    1724             : {
    1725           0 :     mCommissioningStage = CommissioningStage::kSecurePairing;
    1726           0 :     if (mPairingDelegate == nullptr)
    1727             :     {
    1728           0 :         return;
    1729             :     }
    1730           0 :     mPairingDelegate->OnCommissioningComplete(nodeId, completionStatus.err);
    1731           0 :     PeerId peerId(GetCompressedFabricId(), nodeId);
    1732           0 :     if (completionStatus.err == CHIP_NO_ERROR)
    1733             :     {
    1734           0 :         mPairingDelegate->OnCommissioningSuccess(peerId);
    1735             :     }
    1736             :     else
    1737             :     {
    1738             :         // TODO: We should propogate detailed error information (commissioningError, networkCommissioningStatus) from
    1739             :         // completionStatus.
    1740           0 :         mPairingDelegate->OnCommissioningFailure(peerId, completionStatus.err, completionStatus.failedStage.ValueOr(kError),
    1741           0 :                                                  completionStatus.attestationResult);
    1742             :     }
    1743             : }
    1744             : 
    1745           0 : void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report)
    1746             : {
    1747             :     // Once this stage is complete, reset mDeviceBeingCommissioned - this will be reset when the delegate calls the next step.
    1748             :     MATTER_TRACE_SCOPE("CommissioningStageComplete", "DeviceCommissioner");
    1749           0 :     if (mDeviceBeingCommissioned == nullptr)
    1750             :     {
    1751             :         // We are getting a stray callback (e.g. due to un-cancellable
    1752             :         // operations) when we are not in fact commissioning anything.  Just
    1753             :         // ignore it.
    1754           0 :         return;
    1755             :     }
    1756             : 
    1757           0 :     NodeId nodeId            = mDeviceBeingCommissioned->GetDeviceId();
    1758           0 :     DeviceProxy * proxy      = mDeviceBeingCommissioned;
    1759           0 :     mDeviceBeingCommissioned = nullptr;
    1760             : 
    1761           0 :     if (mPairingDelegate != nullptr)
    1762             :     {
    1763           0 :         mPairingDelegate->OnCommissioningStatusUpdate(PeerId(GetCompressedFabricId(), nodeId), mCommissioningStage, err);
    1764             :     }
    1765             : 
    1766           0 :     if (mCommissioningDelegate == nullptr)
    1767             :     {
    1768           0 :         return;
    1769             :     }
    1770           0 :     report.stageCompleted = mCommissioningStage;
    1771           0 :     CHIP_ERROR status     = mCommissioningDelegate->CommissioningStepFinished(err, report);
    1772           0 :     if (status != CHIP_NO_ERROR)
    1773             :     {
    1774             :         // Commissioning delegate will only return error if it failed to perform the appropriate commissioning step.
    1775             :         // In this case, we should complete the commissioning for it.
    1776           0 :         CompletionStatus completionStatus;
    1777           0 :         completionStatus.err         = status;
    1778           0 :         completionStatus.failedStage = MakeOptional(report.stageCompleted);
    1779           0 :         mCommissioningStage          = CommissioningStage::kCleanup;
    1780           0 :         mDeviceBeingCommissioned     = proxy;
    1781           0 :         CleanupCommissioning(proxy, nodeId, completionStatus);
    1782           0 :     }
    1783             : }
    1784             : 
    1785           0 : void DeviceCommissioner::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
    1786             :                                              const SessionHandle & sessionHandle)
    1787             : {
    1788             :     // CASE session established.
    1789           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1790           0 :     VerifyOrReturn(commissioner != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring"));
    1791             : 
    1792           0 :     if (commissioner->mCommissioningStage != CommissioningStage::kFindOperational)
    1793             :     {
    1794             :         // This call is definitely not us finding our commissionee device.
    1795             :         // This is presumably us trying to re-establish CASE on MRP failure.
    1796           0 :         return;
    1797             :     }
    1798             : 
    1799           0 :     if (commissioner->mDeviceBeingCommissioned == nullptr ||
    1800           0 :         commissioner->mDeviceBeingCommissioned->GetDeviceId() != sessionHandle->GetPeer().GetNodeId())
    1801             :     {
    1802             :         // Not the device we are trying to commission.
    1803           0 :         return;
    1804             :     }
    1805             : 
    1806           0 :     if (commissioner->mCommissioningDelegate != nullptr)
    1807             :     {
    1808           0 :         CommissioningDelegate::CommissioningReport report;
    1809           0 :         report.Set<OperationalNodeFoundData>(OperationalNodeFoundData(OperationalDeviceProxy(&exchangeMgr, sessionHandle)));
    1810           0 :         commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
    1811           0 :     }
    1812             : }
    1813             : 
    1814           0 : void DeviceCommissioner::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
    1815             : {
    1816             :     // CASE session establishment failed.
    1817           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    1818             : 
    1819           0 :     ChipLogProgress(Controller, "Device connection failed. Error %s", ErrorStr(error));
    1820           0 :     VerifyOrReturn(commissioner != nullptr,
    1821             :                    ChipLogProgress(Controller, "Device connection failure callback with null context. Ignoring"));
    1822             : 
    1823             :     // Ensure that commissioning stage advancement is done based on seeing an error.
    1824           0 :     if (error == CHIP_NO_ERROR)
    1825             :     {
    1826           0 :         ChipLogError(Controller, "Device connection failed without a valid error code. Making one up.");
    1827           0 :         error = CHIP_ERROR_INTERNAL;
    1828             :     }
    1829             : 
    1830           0 :     if (commissioner->mDeviceBeingCommissioned == nullptr ||
    1831           0 :         commissioner->mDeviceBeingCommissioned->GetDeviceId() != peerId.GetNodeId())
    1832             :     {
    1833             :         // Not the device we are trying to commission.
    1834           0 :         return;
    1835             :     }
    1836             : 
    1837           0 :     if (commissioner->mCommissioningStage == CommissioningStage::kFindOperational &&
    1838           0 :         commissioner->mCommissioningDelegate != nullptr)
    1839             :     {
    1840           0 :         commissioner->CommissioningStageComplete(error);
    1841             :     }
    1842             : }
    1843             : 
    1844             : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
    1845             : // No specific action to take on either success or failure here; we're just
    1846             : // trying to bump the fail-safe, and if that fails it's not clear there's much
    1847             : // we can to with that.
    1848           0 : static void OnExtendFailsafeForCASERetryFailure(void * context, CHIP_ERROR error)
    1849             : {
    1850           0 :     ChipLogError(Controller, "Failed to extend fail-safe for CASE retry: %" CHIP_ERROR_FORMAT, error.Format());
    1851           0 : }
    1852             : static void
    1853           0 : OnExtendFailsafeForCASERetrySuccess(void * context,
    1854             :                                     const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
    1855             : {
    1856           0 :     ChipLogProgress(Controller, "Status of extending fail-safe for CASE retry: %u", to_underlying(data.errorCode));
    1857           0 : }
    1858             : 
    1859           0 : void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error,
    1860             :                                                    System::Clock::Seconds16 retryTimeout)
    1861             : {
    1862           0 :     ChipLogError(Controller,
    1863             :                  "Session establishment failed for " ChipLogFormatScopedNodeId ", error: %" CHIP_ERROR_FORMAT
    1864             :                  ".  Next retry expected to get a response to Sigma1 or fail within %d seconds",
    1865             :                  ChipLogValueScopedNodeId(peerId), error.Format(), retryTimeout.count());
    1866             : 
    1867           0 :     auto self = static_cast<DeviceCommissioner *>(context);
    1868             : 
    1869             :     // We need to do the fail-safe arming over the PASE session.
    1870           0 :     auto * commissioneeDevice = self->FindCommissioneeDevice(peerId.GetNodeId());
    1871           0 :     if (!commissioneeDevice)
    1872             :     {
    1873             :         // Commissioning canceled, presumably.  Just ignore the notification,
    1874             :         // not much we can do here.
    1875           0 :         return;
    1876             :     }
    1877             : 
    1878             :     // Extend by the default failsafe timeout plus our retry timeout, so we can
    1879             :     // be sure the fail-safe will not expire before we try the next time, if
    1880             :     // there will be a next time.
    1881             :     //
    1882             :     // TODO: Make it possible for our clients to control the exact timeout here?
    1883             :     uint16_t failsafeTimeout;
    1884           0 :     if (UINT16_MAX - retryTimeout.count() < kDefaultFailsafeTimeout)
    1885             :     {
    1886           0 :         failsafeTimeout = UINT16_MAX;
    1887             :     }
    1888             :     else
    1889             :     {
    1890           0 :         failsafeTimeout = static_cast<uint16_t>(retryTimeout.count() + kDefaultFailsafeTimeout);
    1891             :     }
    1892             :     // A false return from ExtendArmFailSafe is fine; we don't want to make the
    1893             :     // fail-safe shorter here.
    1894           0 :     self->ExtendArmFailSafe(commissioneeDevice, CommissioningStage::kFindOperational, failsafeTimeout,
    1895           0 :                             MakeOptional(kMinimumCommissioningStepTimeout), OnExtendFailsafeForCASERetrySuccess,
    1896             :                             OnExtendFailsafeForCASERetryFailure);
    1897             : }
    1898             : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
    1899             : 
    1900             : // ClusterStateCache::Callback impl
    1901           0 : void DeviceCommissioner::OnDone(app::ReadClient *)
    1902             : {
    1903           0 :     mReadClient = nullptr;
    1904           0 :     switch (mCommissioningStage)
    1905             :     {
    1906           0 :     case CommissioningStage::kReadCommissioningInfo:
    1907             :         // Silently complete the stage, data will be saved in attribute cache and
    1908             :         // will be parsed after all ReadCommissioningInfo stages are completed.
    1909           0 :         CommissioningStageComplete(CHIP_NO_ERROR);
    1910           0 :         break;
    1911           0 :     case CommissioningStage::kReadCommissioningInfo2:
    1912             :         // Note: Only parse commissioning info in the last ReadCommissioningInfo stage.
    1913           0 :         ParseCommissioningInfo();
    1914           0 :         break;
    1915           0 :     default:
    1916           0 :         break;
    1917             :     }
    1918           0 : }
    1919             : 
    1920           0 : void DeviceCommissioner::ParseCommissioningInfo()
    1921             : {
    1922           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1923           0 :     ReadCommissioningInfo info;
    1924             : 
    1925           0 :     err = ParseCommissioningInfo1(info);
    1926           0 :     if (err == CHIP_NO_ERROR)
    1927             :     {
    1928           0 :         err = ParseCommissioningInfo2(info);
    1929             :     }
    1930             : 
    1931             :     // Move ownership of mAttributeCache to the stack, but don't release it until this function returns.
    1932             :     // This way we don't have to make a copy while parsing commissioning info, and it won't
    1933             :     // affect future commissioning steps.
    1934             :     //
    1935             :     // The stack reference needs to survive until CommissioningStageComplete and OnReadCommissioningInfo
    1936             :     // return.
    1937           0 :     auto attributeCache = std::move(mAttributeCache);
    1938             : 
    1939           0 :     if (mPairingDelegate != nullptr)
    1940             :     {
    1941           0 :         mPairingDelegate->OnReadCommissioningInfo(info);
    1942             :     }
    1943             : 
    1944           0 :     CommissioningDelegate::CommissioningReport report;
    1945           0 :     report.Set<ReadCommissioningInfo>(info);
    1946           0 :     CommissioningStageComplete(err, report);
    1947           0 : }
    1948             : 
    1949           0 : CHIP_ERROR DeviceCommissioner::ParseCommissioningInfo1(ReadCommissioningInfo & info)
    1950             : {
    1951             :     CHIP_ERROR err;
    1952           0 :     CHIP_ERROR return_err = CHIP_NO_ERROR;
    1953             : 
    1954             :     // Try to parse as much as we can here before returning, even if attributes
    1955             :     // are missing or cannot be decoded.
    1956             :     {
    1957             :         using namespace chip::app::Clusters::GeneralCommissioning;
    1958             :         using namespace chip::app::Clusters::GeneralCommissioning::Attributes;
    1959             : 
    1960           0 :         BasicCommissioningInfo::TypeInfo::DecodableType basicInfo;
    1961           0 :         err = mAttributeCache->Get<BasicCommissioningInfo::TypeInfo>(kRootEndpointId, basicInfo);
    1962           0 :         if (err == CHIP_NO_ERROR)
    1963             :         {
    1964           0 :             info.general.recommendedFailsafe = basicInfo.failSafeExpiryLengthSeconds;
    1965             :         }
    1966             :         else
    1967             :         {
    1968           0 :             ChipLogError(Controller, "Failed to read BasicCommissioningInfo: %" CHIP_ERROR_FORMAT, err.Format());
    1969           0 :             return_err = err;
    1970             :         }
    1971             : 
    1972           0 :         err = mAttributeCache->Get<RegulatoryConfig::TypeInfo>(kRootEndpointId, info.general.currentRegulatoryLocation);
    1973           0 :         if (err != CHIP_NO_ERROR)
    1974             :         {
    1975           0 :             ChipLogError(Controller, "Failed to read RegulatoryConfig: %" CHIP_ERROR_FORMAT, err.Format());
    1976           0 :             return_err = err;
    1977             :         }
    1978             : 
    1979           0 :         err = mAttributeCache->Get<LocationCapability::TypeInfo>(kRootEndpointId, info.general.locationCapability);
    1980           0 :         if (err != CHIP_NO_ERROR)
    1981             :         {
    1982           0 :             ChipLogError(Controller, "Failed to read LocationCapability: %" CHIP_ERROR_FORMAT, err.Format());
    1983           0 :             return_err = err;
    1984             :         }
    1985             : 
    1986           0 :         err = mAttributeCache->Get<Breadcrumb::TypeInfo>(kRootEndpointId, info.general.breadcrumb);
    1987           0 :         if (err != CHIP_NO_ERROR)
    1988             :         {
    1989           0 :             ChipLogError(Controller, "Failed to read Breadcrumb: %" CHIP_ERROR_FORMAT, err.Format());
    1990           0 :             return_err = err;
    1991             :         }
    1992             :     }
    1993             : 
    1994             :     {
    1995             :         using namespace chip::app::Clusters::BasicInformation;
    1996             :         using namespace chip::app::Clusters::BasicInformation::Attributes;
    1997             : 
    1998           0 :         err        = mAttributeCache->Get<VendorID::TypeInfo>(kRootEndpointId, info.basic.vendorId);
    1999           0 :         return_err = err == CHIP_NO_ERROR ? return_err : err;
    2000             : 
    2001           0 :         err        = mAttributeCache->Get<ProductID::TypeInfo>(kRootEndpointId, info.basic.productId);
    2002           0 :         return_err = err == CHIP_NO_ERROR ? return_err : err;
    2003             :     }
    2004             :     // Try to parse as much as we can here before returning, even if this is an error.
    2005           0 :     return_err = err == CHIP_NO_ERROR ? return_err : err;
    2006             : 
    2007             :     // Set the network cluster endpoints first so we can match up the connection
    2008             :     // times.  Note that here we don't know what endpoints the network
    2009             :     // commissioning clusters might be on.
    2010           0 :     err = mAttributeCache->ForEachAttribute(
    2011           0 :         app::Clusters::NetworkCommissioning::Id, [this, &info](const app::ConcreteAttributePath & path) {
    2012             :             using namespace chip::app::Clusters;
    2013             :             using namespace chip::app::Clusters::NetworkCommissioning::Attributes;
    2014           0 :             if (path.mAttributeId != FeatureMap::Id)
    2015             :             {
    2016           0 :                 return CHIP_NO_ERROR;
    2017             :             }
    2018             :             TLV::TLVReader reader;
    2019           0 :             if (this->mAttributeCache->Get(path, reader) == CHIP_NO_ERROR)
    2020             :             {
    2021           0 :                 BitFlags<NetworkCommissioning::Feature> features;
    2022           0 :                 if (app::DataModel::Decode(reader, features) == CHIP_NO_ERROR)
    2023             :                 {
    2024           0 :                     if (features.Has(NetworkCommissioning::Feature::kWiFiNetworkInterface))
    2025             :                     {
    2026           0 :                         ChipLogProgress(Controller, "----- NetworkCommissioning Features: has WiFi. endpointid = %u",
    2027             :                                         path.mEndpointId);
    2028           0 :                         info.network.wifi.endpoint = path.mEndpointId;
    2029             :                     }
    2030           0 :                     else if (features.Has(NetworkCommissioning::Feature::kThreadNetworkInterface))
    2031             :                     {
    2032           0 :                         ChipLogProgress(Controller, "----- NetworkCommissioning Features: has Thread. endpointid = %u",
    2033             :                                         path.mEndpointId);
    2034           0 :                         info.network.thread.endpoint = path.mEndpointId;
    2035             :                     }
    2036           0 :                     else if (features.Has(NetworkCommissioning::Feature::kEthernetNetworkInterface))
    2037             :                     {
    2038           0 :                         ChipLogProgress(Controller, "----- NetworkCommissioning Features: has Ethernet. endpointid = %u",
    2039             :                                         path.mEndpointId);
    2040           0 :                         info.network.eth.endpoint = path.mEndpointId;
    2041             :                     }
    2042             :                     else
    2043             :                     {
    2044           0 :                         ChipLogProgress(Controller, "----- NetworkCommissioning Features: no features.");
    2045             :                         // TODO: Gross workaround for the empty feature map on all clusters. Remove.
    2046           0 :                         if (info.network.thread.endpoint == kInvalidEndpointId)
    2047             :                         {
    2048           0 :                             info.network.thread.endpoint = path.mEndpointId;
    2049             :                         }
    2050           0 :                         if (info.network.wifi.endpoint == kInvalidEndpointId)
    2051             :                         {
    2052           0 :                             info.network.wifi.endpoint = path.mEndpointId;
    2053             :                         }
    2054             :                     }
    2055             :                 }
    2056             :             }
    2057           0 :             return CHIP_NO_ERROR;
    2058             :         });
    2059           0 :     return_err = err == CHIP_NO_ERROR ? return_err : err;
    2060             : 
    2061           0 :     err = mAttributeCache->ForEachAttribute(
    2062           0 :         app::Clusters::NetworkCommissioning::Id, [this, &info](const app::ConcreteAttributePath & path) {
    2063             :             using namespace chip::app::Clusters::NetworkCommissioning::Attributes;
    2064           0 :             if (path.mAttributeId != ConnectMaxTimeSeconds::Id)
    2065             :             {
    2066           0 :                 return CHIP_NO_ERROR;
    2067             :             }
    2068             :             ConnectMaxTimeSeconds::TypeInfo::DecodableArgType time;
    2069           0 :             ReturnErrorOnFailure(this->mAttributeCache->Get<ConnectMaxTimeSeconds::TypeInfo>(path, time));
    2070           0 :             if (path.mEndpointId == info.network.wifi.endpoint)
    2071             :             {
    2072           0 :                 info.network.wifi.minConnectionTime = time;
    2073             :             }
    2074           0 :             else if (path.mEndpointId == info.network.thread.endpoint)
    2075             :             {
    2076           0 :                 info.network.thread.minConnectionTime = time;
    2077             :             }
    2078           0 :             else if (path.mEndpointId == info.network.eth.endpoint)
    2079             :             {
    2080           0 :                 info.network.eth.minConnectionTime = time;
    2081             :             }
    2082           0 :             return CHIP_NO_ERROR;
    2083             :         });
    2084           0 :     return_err = err == CHIP_NO_ERROR ? return_err : err;
    2085             : 
    2086           0 :     ParseTimeSyncInfo(info);
    2087             : 
    2088           0 :     if (return_err != CHIP_NO_ERROR)
    2089             :     {
    2090           0 :         ChipLogError(Controller, "Error parsing commissioning information");
    2091             :     }
    2092             : 
    2093           0 :     return return_err;
    2094             : }
    2095             : 
    2096           0 : void DeviceCommissioner::ParseTimeSyncInfo(ReadCommissioningInfo & info)
    2097             : {
    2098             :     using namespace app::Clusters;
    2099             : 
    2100             :     CHIP_ERROR err;
    2101             :     // If we fail to get the feature map, there's no viable time cluster, don't set anything.
    2102             :     TimeSynchronization::Attributes::FeatureMap::TypeInfo::DecodableType featureMap;
    2103           0 :     err = mAttributeCache->Get<TimeSynchronization::Attributes::FeatureMap::TypeInfo>(kRootEndpointId, featureMap);
    2104           0 :     if (err != CHIP_NO_ERROR)
    2105             :     {
    2106           0 :         info.requiresUTC               = false;
    2107           0 :         info.requiresTimeZone          = false;
    2108           0 :         info.requiresDefaultNTP        = false;
    2109           0 :         info.requiresTrustedTimeSource = false;
    2110           0 :         return;
    2111             :     }
    2112           0 :     info.requiresUTC               = true;
    2113           0 :     info.requiresTimeZone          = featureMap & chip::to_underlying(TimeSynchronization::Feature::kTimeZone);
    2114           0 :     info.requiresDefaultNTP        = featureMap & chip::to_underlying(TimeSynchronization::Feature::kNTPClient);
    2115           0 :     info.requiresTrustedTimeSource = featureMap & chip::to_underlying(TimeSynchronization::Feature::kTimeSyncClient);
    2116             : 
    2117           0 :     if (info.requiresTimeZone)
    2118             :     {
    2119           0 :         err = mAttributeCache->Get<TimeSynchronization::Attributes::TimeZoneListMaxSize::TypeInfo>(kRootEndpointId,
    2120           0 :                                                                                                    info.maxTimeZoneSize);
    2121           0 :         if (err != CHIP_NO_ERROR)
    2122             :         {
    2123             :             // This information should be available, let's do our best with what we have, but we can't set
    2124             :             // the time zone without this information
    2125           0 :             info.requiresTimeZone = false;
    2126             :         }
    2127           0 :         err =
    2128           0 :             mAttributeCache->Get<TimeSynchronization::Attributes::DSTOffsetListMaxSize::TypeInfo>(kRootEndpointId, info.maxDSTSize);
    2129           0 :         if (err != CHIP_NO_ERROR)
    2130             :         {
    2131           0 :             info.requiresTimeZone = false;
    2132             :         }
    2133             :     }
    2134           0 :     if (info.requiresDefaultNTP)
    2135             :     {
    2136           0 :         TimeSynchronization::Attributes::DefaultNTP::TypeInfo::DecodableType defaultNTP;
    2137           0 :         err = mAttributeCache->Get<TimeSynchronization::Attributes::DefaultNTP::TypeInfo>(kRootEndpointId, defaultNTP);
    2138           0 :         if (err == CHIP_NO_ERROR && (!defaultNTP.IsNull()) && (defaultNTP.Value().size() != 0))
    2139             :         {
    2140           0 :             info.requiresDefaultNTP = false;
    2141             :         }
    2142           0 :     }
    2143           0 :     if (info.requiresTrustedTimeSource)
    2144             :     {
    2145           0 :         TimeSynchronization::Attributes::TrustedTimeSource::TypeInfo::DecodableType trustedTimeSource;
    2146           0 :         err =
    2147           0 :             mAttributeCache->Get<TimeSynchronization::Attributes::TrustedTimeSource::TypeInfo>(kRootEndpointId, trustedTimeSource);
    2148             : 
    2149           0 :         if (err == CHIP_NO_ERROR && !trustedTimeSource.IsNull())
    2150             :         {
    2151           0 :             info.requiresTrustedTimeSource = false;
    2152             :         }
    2153           0 :     }
    2154             : }
    2155             : 
    2156           0 : CHIP_ERROR DeviceCommissioner::ParseCommissioningInfo2(ReadCommissioningInfo & info)
    2157             : {
    2158           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2159             : 
    2160             :     using namespace chip::app::Clusters::GeneralCommissioning::Attributes;
    2161             : 
    2162           0 :     if (mAttributeCache->Get<SupportsConcurrentConnection::TypeInfo>(kRootEndpointId, info.supportsConcurrentConnection) !=
    2163           0 :         CHIP_NO_ERROR)
    2164             :     {
    2165             :         // May not be present so don't return the error code, non fatal, default concurrent
    2166           0 :         ChipLogError(Controller, "Failed to read SupportsConcurrentConnection: %" CHIP_ERROR_FORMAT, err.Format());
    2167           0 :         info.supportsConcurrentConnection = true;
    2168             :     }
    2169             : 
    2170           0 :     err = ParseFabrics(info);
    2171             : 
    2172           0 :     if (err == CHIP_NO_ERROR)
    2173             :     {
    2174           0 :         err = ParseICDInfo(info);
    2175             :     }
    2176             : 
    2177           0 :     return err;
    2178             : }
    2179             : 
    2180           0 : CHIP_ERROR DeviceCommissioner::ParseFabrics(ReadCommissioningInfo & info)
    2181             : {
    2182             :     CHIP_ERROR err;
    2183           0 :     CHIP_ERROR return_err = CHIP_NO_ERROR;
    2184             : 
    2185             :     // We might not have requested a Fabrics attribute at all, so not having a
    2186             :     // value for it is not an error.
    2187           0 :     err = mAttributeCache->ForEachAttribute(OperationalCredentials::Id, [this, &info](const app::ConcreteAttributePath & path) {
    2188             :         using namespace chip::app::Clusters::OperationalCredentials::Attributes;
    2189             :         // this code is checking if the device is already on the commissioner's fabric.
    2190             :         // if a matching fabric is found, then remember the nodeId so that the commissioner
    2191             :         // can, if it decides to, cancel commissioning (before it fails in AddNoc) and know
    2192             :         // the device's nodeId on its fabric.
    2193           0 :         switch (path.mAttributeId)
    2194             :         {
    2195           0 :         case Fabrics::Id: {
    2196           0 :             Fabrics::TypeInfo::DecodableType fabrics;
    2197           0 :             ReturnErrorOnFailure(this->mAttributeCache->Get<Fabrics::TypeInfo>(path, fabrics));
    2198             :             // this is a best effort attempt to find a matching fabric, so no error checking on iter
    2199           0 :             auto iter = fabrics.begin();
    2200           0 :             while (iter.Next())
    2201             :             {
    2202           0 :                 auto & fabricDescriptor = iter.GetValue();
    2203           0 :                 ChipLogProgress(Controller,
    2204             :                                 "DeviceCommissioner::OnDone - fabric.vendorId=0x%04X fabric.fabricId=0x" ChipLogFormatX64
    2205             :                                 " fabric.nodeId=0x" ChipLogFormatX64,
    2206             :                                 fabricDescriptor.vendorID, ChipLogValueX64(fabricDescriptor.fabricID),
    2207             :                                 ChipLogValueX64(fabricDescriptor.nodeID));
    2208           0 :                 if (GetFabricId() == fabricDescriptor.fabricID)
    2209             :                 {
    2210           0 :                     ChipLogProgress(Controller, "DeviceCommissioner::OnDone - found a matching fabric id");
    2211           0 :                     chip::ByteSpan rootKeySpan = fabricDescriptor.rootPublicKey;
    2212           0 :                     if (rootKeySpan.size() != Crypto::kP256_PublicKey_Length)
    2213             :                     {
    2214           0 :                         ChipLogError(Controller, "DeviceCommissioner::OnDone - fabric root key size mismatch %u != %u",
    2215             :                                      static_cast<unsigned>(rootKeySpan.size()),
    2216             :                                      static_cast<unsigned>(Crypto::kP256_PublicKey_Length));
    2217           0 :                         continue;
    2218             :                     }
    2219           0 :                     P256PublicKeySpan rootPubKeySpan(rootKeySpan.data());
    2220           0 :                     Crypto::P256PublicKey deviceRootPublicKey(rootPubKeySpan);
    2221             : 
    2222           0 :                     Crypto::P256PublicKey commissionerRootPublicKey;
    2223           0 :                     if (CHIP_NO_ERROR != GetRootPublicKey(commissionerRootPublicKey))
    2224             :                     {
    2225           0 :                         ChipLogError(Controller, "DeviceCommissioner::OnDone - error reading commissioner root public key");
    2226             :                     }
    2227           0 :                     else if (commissionerRootPublicKey.Matches(deviceRootPublicKey))
    2228             :                     {
    2229           0 :                         ChipLogProgress(Controller, "DeviceCommissioner::OnDone - fabric root keys match");
    2230           0 :                         info.remoteNodeId = fabricDescriptor.nodeID;
    2231             :                     }
    2232           0 :                 }
    2233             :             }
    2234             : 
    2235           0 :             return CHIP_NO_ERROR;
    2236           0 :         }
    2237           0 :         default:
    2238           0 :             return CHIP_NO_ERROR;
    2239             :         }
    2240             :     });
    2241             : 
    2242           0 :     if (mPairingDelegate != nullptr)
    2243             :     {
    2244           0 :         mPairingDelegate->OnFabricCheck(info.remoteNodeId);
    2245             :     }
    2246             : 
    2247           0 :     return return_err;
    2248             : }
    2249             : 
    2250           0 : CHIP_ERROR DeviceCommissioner::ParseICDInfo(ReadCommissioningInfo & info)
    2251             : {
    2252             :     using chip::app::Clusters::IcdManagement::UserActiveModeTriggerBitmap;
    2253             : 
    2254             :     CHIP_ERROR err;
    2255             :     IcdManagement::Attributes::FeatureMap::TypeInfo::DecodableType featureMap;
    2256           0 :     bool hasUserActiveModeTrigger = false;
    2257             : 
    2258           0 :     err = mAttributeCache->Get<IcdManagement::Attributes::FeatureMap::TypeInfo>(kRootEndpointId, featureMap);
    2259           0 :     if (err == CHIP_NO_ERROR)
    2260             :     {
    2261           0 :         info.icd.isLIT                  = !!(featureMap & to_underlying(IcdManagement::Feature::kLongIdleTimeSupport));
    2262           0 :         info.icd.checkInProtocolSupport = !!(featureMap & to_underlying(IcdManagement::Feature::kCheckInProtocolSupport));
    2263           0 :         hasUserActiveModeTrigger        = !!(featureMap & to_underlying(IcdManagement::Feature::kUserActiveModeTrigger));
    2264             :     }
    2265           0 :     else if (err == CHIP_ERROR_KEY_NOT_FOUND)
    2266             :     {
    2267             :         // This key is optional so not an error
    2268           0 :         info.icd.isLIT = false;
    2269           0 :         err            = CHIP_NO_ERROR;
    2270             :     }
    2271           0 :     else if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
    2272             :     {
    2273           0 :         app::StatusIB statusIB;
    2274           0 :         err = mAttributeCache->GetStatus(
    2275           0 :             app::ConcreteAttributePath(kRootEndpointId, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id), statusIB);
    2276           0 :         if (err == CHIP_NO_ERROR)
    2277             :         {
    2278           0 :             if (statusIB.mStatus == Protocols::InteractionModel::Status::UnsupportedCluster)
    2279             :             {
    2280           0 :                 info.icd.isLIT = false;
    2281             :             }
    2282             :             else
    2283             :             {
    2284           0 :                 err = statusIB.ToChipError();
    2285             :             }
    2286             :         }
    2287           0 :     }
    2288             : 
    2289           0 :     ReturnErrorOnFailure(err);
    2290             : 
    2291           0 :     info.icd.userActiveModeTriggerHint.ClearAll();
    2292           0 :     info.icd.userActiveModeTriggerInstruction = CharSpan();
    2293           0 :     if (hasUserActiveModeTrigger)
    2294             :     {
    2295             :         // Intentionally ignore errors since they are not mandatory.
    2296           0 :         bool activeModeTriggerInstructionRequired = false;
    2297             : 
    2298           0 :         err = mAttributeCache->Get<IcdManagement::Attributes::UserActiveModeTriggerHint::TypeInfo>(
    2299           0 :             kRootEndpointId, info.icd.userActiveModeTriggerHint);
    2300           0 :         if (err != CHIP_NO_ERROR)
    2301             :         {
    2302           0 :             ChipLogError(Controller, "IcdManagement.UserActiveModeTriggerHint expected, but failed to read.");
    2303           0 :             return err;
    2304             :         }
    2305             : 
    2306           0 :         activeModeTriggerInstructionRequired = info.icd.userActiveModeTriggerHint.HasAny(
    2307           0 :             UserActiveModeTriggerBitmap::kCustomInstruction, UserActiveModeTriggerBitmap::kActuateSensorSeconds,
    2308           0 :             UserActiveModeTriggerBitmap::kActuateSensorTimes, UserActiveModeTriggerBitmap::kActuateSensorLightsBlink,
    2309           0 :             UserActiveModeTriggerBitmap::kResetButtonLightsBlink, UserActiveModeTriggerBitmap::kResetButtonSeconds,
    2310           0 :             UserActiveModeTriggerBitmap::kResetButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonSeconds,
    2311           0 :             UserActiveModeTriggerBitmap::kSetupButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonTimes,
    2312           0 :             UserActiveModeTriggerBitmap::kAppDefinedButton);
    2313             : 
    2314           0 :         if (activeModeTriggerInstructionRequired)
    2315             :         {
    2316           0 :             err = mAttributeCache->Get<IcdManagement::Attributes::UserActiveModeTriggerInstruction::TypeInfo>(
    2317           0 :                 kRootEndpointId, info.icd.userActiveModeTriggerInstruction);
    2318           0 :             if (err != CHIP_NO_ERROR)
    2319             :             {
    2320           0 :                 ChipLogError(Controller,
    2321             :                              "IcdManagement.UserActiveModeTriggerInstruction expected for given active mode trigger hint, but "
    2322             :                              "failed to read.");
    2323           0 :                 return err;
    2324             :             }
    2325             :         }
    2326             :     }
    2327             : 
    2328           0 :     return err;
    2329             : }
    2330             : 
    2331           0 : void DeviceCommissioner::OnArmFailSafe(void * context,
    2332             :                                        const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
    2333             : {
    2334           0 :     CommissioningDelegate::CommissioningReport report;
    2335           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2336             : 
    2337           0 :     ChipLogProgress(Controller, "Received ArmFailSafe response errorCode=%u", to_underlying(data.errorCode));
    2338           0 :     if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
    2339             :     {
    2340           0 :         err = CHIP_ERROR_INTERNAL;
    2341           0 :         report.Set<CommissioningErrorInfo>(data.errorCode);
    2342             :     }
    2343             : 
    2344           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2345           0 :     commissioner->CommissioningStageComplete(err, report);
    2346           0 : }
    2347             : 
    2348           0 : void DeviceCommissioner::OnSetRegulatoryConfigResponse(
    2349             :     void * context, const GeneralCommissioning::Commands::SetRegulatoryConfigResponse::DecodableType & data)
    2350             : {
    2351           0 :     CommissioningDelegate::CommissioningReport report;
    2352           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2353             : 
    2354           0 :     ChipLogProgress(Controller, "Received SetRegulatoryConfig response errorCode=%u", to_underlying(data.errorCode));
    2355           0 :     if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
    2356             :     {
    2357           0 :         err = CHIP_ERROR_INTERNAL;
    2358           0 :         report.Set<CommissioningErrorInfo>(data.errorCode);
    2359             :     }
    2360           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2361           0 :     commissioner->CommissioningStageComplete(err, report);
    2362           0 : }
    2363             : 
    2364           0 : void DeviceCommissioner::OnSetTimeZoneResponse(void * context,
    2365             :                                                const TimeSynchronization::Commands::SetTimeZoneResponse::DecodableType & data)
    2366             : {
    2367           0 :     CommissioningDelegate::CommissioningReport report;
    2368           0 :     CHIP_ERROR err                    = CHIP_NO_ERROR;
    2369           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2370             :     TimeZoneResponseInfo info;
    2371           0 :     info.requiresDSTOffsets = data.DSTOffsetRequired;
    2372           0 :     report.Set<TimeZoneResponseInfo>(info);
    2373           0 :     commissioner->CommissioningStageComplete(err, report);
    2374           0 : }
    2375             : 
    2376           0 : void DeviceCommissioner::OnSetUTCError(void * context, CHIP_ERROR error)
    2377             : {
    2378             :     // For SetUTCTime, we don't actually care if the commissionee didn't want out time, that's its choice
    2379           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2380           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    2381           0 : }
    2382             : 
    2383           0 : void DeviceCommissioner::OnScanNetworksFailure(void * context, CHIP_ERROR error)
    2384             : {
    2385           0 :     ChipLogProgress(Controller, "Received ScanNetworks failure response %" CHIP_ERROR_FORMAT, error.Format());
    2386             : 
    2387           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2388             : 
    2389             :     // advance to the kNeedsNetworkCreds waiting step
    2390             :     // clear error so that we don't abort the commissioning when ScanNetworks fails
    2391           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    2392             : 
    2393           0 :     if (commissioner->GetPairingDelegate() != nullptr)
    2394             :     {
    2395           0 :         commissioner->GetPairingDelegate()->OnScanNetworksFailure(error);
    2396             :     }
    2397           0 : }
    2398             : 
    2399           0 : void DeviceCommissioner::OnScanNetworksResponse(void * context,
    2400             :                                                 const NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & data)
    2401             : {
    2402           0 :     CommissioningDelegate::CommissioningReport report;
    2403             : 
    2404           0 :     ChipLogProgress(Controller, "Received ScanNetwork response, networkingStatus=%u debugText=%s",
    2405             :                     to_underlying(data.networkingStatus),
    2406             :                     (data.debugText.HasValue() ? std::string(data.debugText.Value().data(), data.debugText.Value().size()).c_str()
    2407             :                                                : "none provided"));
    2408           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2409             : 
    2410             :     // advance to the kNeedsNetworkCreds waiting step
    2411           0 :     commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
    2412             : 
    2413           0 :     if (commissioner->GetPairingDelegate() != nullptr)
    2414             :     {
    2415           0 :         commissioner->GetPairingDelegate()->OnScanNetworksSuccess(data);
    2416             :     }
    2417           0 : }
    2418             : 
    2419           0 : CHIP_ERROR DeviceCommissioner::NetworkCredentialsReady()
    2420             : {
    2421           0 :     ReturnErrorCodeIf(mCommissioningStage != CommissioningStage::kNeedsNetworkCreds, CHIP_ERROR_INCORRECT_STATE);
    2422             : 
    2423             :     // need to advance to next step
    2424           0 :     CommissioningStageComplete(CHIP_NO_ERROR);
    2425             : 
    2426           0 :     return CHIP_NO_ERROR;
    2427             : }
    2428             : 
    2429           0 : CHIP_ERROR DeviceCommissioner::ICDRegistrationInfoReady()
    2430             : {
    2431           0 :     ReturnErrorCodeIf(mCommissioningStage != CommissioningStage::kICDGetRegistrationInfo, CHIP_ERROR_INCORRECT_STATE);
    2432             : 
    2433             :     // need to advance to next step
    2434           0 :     CommissioningStageComplete(CHIP_NO_ERROR);
    2435             : 
    2436           0 :     return CHIP_NO_ERROR;
    2437             : }
    2438             : 
    2439           0 : void DeviceCommissioner::OnNetworkConfigResponse(void * context,
    2440             :                                                  const NetworkCommissioning::Commands::NetworkConfigResponse::DecodableType & data)
    2441             : {
    2442           0 :     CommissioningDelegate::CommissioningReport report;
    2443           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2444             : 
    2445           0 :     ChipLogProgress(Controller, "Received NetworkConfig response, networkingStatus=%u", to_underlying(data.networkingStatus));
    2446           0 :     if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
    2447             :     {
    2448           0 :         err = CHIP_ERROR_INTERNAL;
    2449           0 :         report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
    2450             :     }
    2451           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2452           0 :     commissioner->CommissioningStageComplete(err, report);
    2453           0 : }
    2454             : 
    2455           0 : void DeviceCommissioner::OnConnectNetworkResponse(
    2456             :     void * context, const NetworkCommissioning::Commands::ConnectNetworkResponse::DecodableType & data)
    2457             : {
    2458           0 :     CommissioningDelegate::CommissioningReport report;
    2459           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2460             : 
    2461           0 :     ChipLogProgress(Controller, "Received ConnectNetwork response, networkingStatus=%u", to_underlying(data.networkingStatus));
    2462           0 :     if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
    2463             :     {
    2464           0 :         err = CHIP_ERROR_INTERNAL;
    2465           0 :         report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
    2466             :     }
    2467           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2468           0 :     commissioner->CommissioningStageComplete(err, report);
    2469           0 : }
    2470             : 
    2471           0 : void DeviceCommissioner::OnCommissioningCompleteResponse(
    2472             :     void * context, const GeneralCommissioning::Commands::CommissioningCompleteResponse::DecodableType & data)
    2473             : {
    2474           0 :     CommissioningDelegate::CommissioningReport report;
    2475           0 :     CHIP_ERROR err = CHIP_NO_ERROR;
    2476             : 
    2477           0 :     ChipLogProgress(Controller, "Received CommissioningComplete response, errorCode=%u", to_underlying(data.errorCode));
    2478           0 :     if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
    2479             :     {
    2480           0 :         err = CHIP_ERROR_INTERNAL;
    2481           0 :         report.Set<CommissioningErrorInfo>(data.errorCode);
    2482             :     }
    2483           0 :     DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
    2484           0 :     commissioner->CommissioningStageComplete(err, report);
    2485           0 : }
    2486             : 
    2487           0 : void DeviceCommissioner::SendCommissioningReadRequest(DeviceProxy * proxy, Optional<System::Clock::Timeout> timeout,
    2488             :                                                       app::AttributePathParams * readPaths, size_t readPathsSize)
    2489             : {
    2490           0 :     app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
    2491           0 :     app::ReadPrepareParams readParams(proxy->GetSecureSession().Value());
    2492           0 :     readParams.mIsFabricFiltered = false;
    2493           0 :     if (timeout.HasValue())
    2494             :     {
    2495           0 :         readParams.mTimeout = timeout.Value();
    2496             :     }
    2497           0 :     readParams.mpAttributePathParamsList    = readPaths;
    2498           0 :     readParams.mAttributePathParamsListSize = readPathsSize;
    2499             : 
    2500             :     // Take ownership of the attribute cache, so it can be released when SendRequest fails.
    2501           0 :     auto attributeCache = std::move(mAttributeCache);
    2502             :     auto readClient     = chip::Platform::MakeUnique<app::ReadClient>(
    2503           0 :         engine, proxy->GetExchangeManager(), attributeCache->GetBufferedCallback(), app::ReadClient::InteractionType::Read);
    2504           0 :     CHIP_ERROR err = readClient->SendRequest(readParams);
    2505           0 :     if (err != CHIP_NO_ERROR)
    2506             :     {
    2507           0 :         ChipLogError(Controller, "Failed to send read request: %" CHIP_ERROR_FORMAT, err.Format());
    2508           0 :         CommissioningStageComplete(err);
    2509           0 :         return;
    2510             :     }
    2511           0 :     mAttributeCache = std::move(attributeCache);
    2512           0 :     mReadClient     = std::move(readClient);
    2513           0 : }
    2514             : 
    2515           0 : void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, CommissioningStage step, CommissioningParameters & params,
    2516             :                                                   CommissioningDelegate * delegate, EndpointId endpoint,
    2517             :                                                   Optional<System::Clock::Timeout> timeout)
    2518             : {
    2519           0 :     if (params.GetCompletionStatus().err == CHIP_NO_ERROR)
    2520             :     {
    2521           0 :         ChipLogProgress(Controller, "Performing next commissioning step '%s'", StageToString(step));
    2522             :     }
    2523             :     else
    2524             :     {
    2525           0 :         ChipLogProgress(Controller, "Performing next commissioning step '%s' with completion status = '%s'", StageToString(step),
    2526             :                         params.GetCompletionStatus().err.AsString());
    2527             :     }
    2528             : 
    2529             :     // For now, we ignore errors coming in from the device since not all commissioning clusters are implemented on the device
    2530             :     // side.
    2531           0 :     mCommissioningStage      = step;
    2532           0 :     mCommissioningDelegate   = delegate;
    2533           0 :     mDeviceBeingCommissioned = proxy;
    2534             :     // TODO: Extend timeouts to the DAC and Opcert requests.
    2535             : 
    2536             :     // TODO(cecille): We probably want something better than this for breadcrumbs.
    2537           0 :     uint64_t breadcrumb = static_cast<uint64_t>(step);
    2538             : 
    2539           0 :     switch (step)
    2540             :     {
    2541           0 :     case CommissioningStage::kArmFailsafe: {
    2542           0 :         VerifyOrDie(endpoint == kRootEndpointId);
    2543             :         // Make sure the fail-safe value we set here actually ends up being used
    2544             :         // no matter what.
    2545           0 :         proxy->SetFailSafeExpirationTimestamp(System::Clock::kZero);
    2546           0 :         VerifyOrDie(ExtendArmFailSafe(proxy, step, params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout), timeout,
    2547             :                                       OnArmFailSafe, OnBasicFailure));
    2548             :     }
    2549           0 :     break;
    2550           0 :     case CommissioningStage::kReadCommissioningInfo: {
    2551           0 :         ChipLogProgress(Controller, "Sending read request for commissioning information");
    2552             :         // Allocate a new ClusterStateCache when starting reading the first batch of attributes.
    2553             :         // The cache will be released in:
    2554             :         // - SendCommissioningReadRequest when failing to send a read request.
    2555             :         // - ParseCommissioningInfo when the last ReadCommissioningInfo stage is completed.
    2556             :         // Currently, we have two ReadCommissioningInfo* stages.
    2557           0 :         mAttributeCache = Platform::MakeUnique<app::ClusterStateCache>(*this);
    2558             : 
    2559             :         // NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
    2560             :         // See R1.1, 2.11.2 Interaction Model Limits
    2561           0 :         app::AttributePathParams readPaths[9];
    2562             :         // Read all the feature maps for all the networking clusters on any endpoint to determine what is supported
    2563           0 :         readPaths[0] = app::AttributePathParams(app::Clusters::NetworkCommissioning::Id,
    2564             :                                                 app::Clusters::NetworkCommissioning::Attributes::FeatureMap::Id);
    2565             :         // Get required general commissioning attributes on this endpoint (recommended failsafe time, regulatory location
    2566             :         // info, breadcrumb)
    2567           0 :         readPaths[1] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
    2568             :                                                 app::Clusters::GeneralCommissioning::Attributes::Breadcrumb::Id);
    2569           0 :         readPaths[2] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
    2570             :                                                 app::Clusters::GeneralCommissioning::Attributes::BasicCommissioningInfo::Id);
    2571           0 :         readPaths[3] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
    2572             :                                                 app::Clusters::GeneralCommissioning::Attributes::RegulatoryConfig::Id);
    2573           0 :         readPaths[4] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
    2574             :                                                 app::Clusters::GeneralCommissioning::Attributes::LocationCapability::Id);
    2575             :         // Read attributes from the basic info cluster (vendor id / product id / software version)
    2576           0 :         readPaths[5] = app::AttributePathParams(endpoint, app::Clusters::BasicInformation::Id,
    2577             :                                                 app::Clusters::BasicInformation::Attributes::VendorID::Id);
    2578           0 :         readPaths[6] = app::AttributePathParams(endpoint, app::Clusters::BasicInformation::Id,
    2579             :                                                 app::Clusters::BasicInformation::Attributes::ProductID::Id);
    2580             :         // Read the requested minimum connection times from all network commissioning clusters
    2581           0 :         readPaths[7] = app::AttributePathParams(app::Clusters::NetworkCommissioning::Id,
    2582             :                                                 app::Clusters::NetworkCommissioning::Attributes::ConnectMaxTimeSeconds::Id);
    2583             :         // Read everything from the time cluster so we can assess what information needs to be set.
    2584           0 :         readPaths[8] = app::AttributePathParams(endpoint, app::Clusters::TimeSynchronization::Id);
    2585             : 
    2586           0 :         SendCommissioningReadRequest(proxy, timeout, readPaths, 9);
    2587             :     }
    2588           0 :     break;
    2589           0 :     case CommissioningStage::kReadCommissioningInfo2: {
    2590           0 :         size_t numberOfAttributes = 0;
    2591             :         // This is done in a separate step since we've already used up all the available read paths in the previous read step
    2592             :         // NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
    2593             :         // See R1.1, 2.11.2 Interaction Model Limits
    2594             : 
    2595             :         // Currently, we have at most 5 attributes to read in this stage.
    2596           0 :         app::AttributePathParams readPaths[5];
    2597             : 
    2598             :         // Mandatory attribute
    2599           0 :         readPaths[numberOfAttributes++] =
    2600           0 :             app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
    2601             :                                      app::Clusters::GeneralCommissioning::Attributes::SupportsConcurrentConnection::Id);
    2602             : 
    2603             :         // Read the current fabrics
    2604           0 :         if (params.GetCheckForMatchingFabric())
    2605             :         {
    2606           0 :             readPaths[numberOfAttributes++] =
    2607           0 :                 app::AttributePathParams(OperationalCredentials::Id, OperationalCredentials::Attributes::Fabrics::Id);
    2608             :         }
    2609             : 
    2610           0 :         if (params.GetICDRegistrationStrategy() != ICDRegistrationStrategy::kIgnore)
    2611             :         {
    2612           0 :             readPaths[numberOfAttributes++] =
    2613           0 :                 app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id);
    2614             :         }
    2615             :         // Always read the active mode trigger hint attributes to notify users about it.
    2616           0 :         readPaths[numberOfAttributes++] =
    2617           0 :             app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::UserActiveModeTriggerHint::Id);
    2618           0 :         readPaths[numberOfAttributes++] =
    2619           0 :             app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::UserActiveModeTriggerInstruction::Id);
    2620             : 
    2621           0 :         SendCommissioningReadRequest(proxy, timeout, readPaths, numberOfAttributes);
    2622             :     }
    2623           0 :     break;
    2624           0 :     case CommissioningStage::kConfigureUTCTime: {
    2625           0 :         TimeSynchronization::Commands::SetUTCTime::Type request;
    2626           0 :         uint64_t kChipEpochUsSinceUnixEpoch = static_cast<uint64_t>(kChipEpochSecondsSinceUnixEpoch) * chip::kMicrosecondsPerSecond;
    2627             :         System::Clock::Microseconds64 utcTime;
    2628           0 :         if (System::SystemClock().GetClock_RealTime(utcTime) != CHIP_NO_ERROR || utcTime.count() <= kChipEpochUsSinceUnixEpoch)
    2629             :         {
    2630             :             // We have no time to give, but that's OK, just complete this stage
    2631           0 :             CommissioningStageComplete(CHIP_NO_ERROR);
    2632           0 :             return;
    2633             :         }
    2634             : 
    2635           0 :         request.UTCTime = utcTime.count() - kChipEpochUsSinceUnixEpoch;
    2636             :         // For now, we assume a seconds granularity
    2637           0 :         request.granularity = TimeSynchronization::GranularityEnum::kSecondsGranularity;
    2638           0 :         CHIP_ERROR err      = SendCommand(proxy, request, OnBasicSuccess, OnSetUTCError, endpoint, timeout);
    2639           0 :         if (err != CHIP_NO_ERROR)
    2640             :         {
    2641             :             // We won't get any async callbacks here, so just complete our stage.
    2642           0 :             ChipLogError(Controller, "Failed to send SetUTCTime command: %" CHIP_ERROR_FORMAT, err.Format());
    2643           0 :             CommissioningStageComplete(err);
    2644           0 :             return;
    2645             :         }
    2646           0 :         break;
    2647           0 :     }
    2648           0 :     case CommissioningStage::kConfigureTimeZone: {
    2649           0 :         if (!params.GetTimeZone().HasValue())
    2650             :         {
    2651           0 :             ChipLogError(Controller, "ConfigureTimeZone stage called with no time zone data");
    2652           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2653           0 :             return;
    2654             :         }
    2655           0 :         TimeSynchronization::Commands::SetTimeZone::Type request;
    2656           0 :         request.timeZone = params.GetTimeZone().Value();
    2657           0 :         CHIP_ERROR err   = SendCommand(proxy, request, OnSetTimeZoneResponse, OnBasicFailure, endpoint, timeout);
    2658           0 :         if (err != CHIP_NO_ERROR)
    2659             :         {
    2660             :             // We won't get any async callbacks here, so just complete our stage.
    2661           0 :             ChipLogError(Controller, "Failed to send SetTimeZone command: %" CHIP_ERROR_FORMAT, err.Format());
    2662           0 :             CommissioningStageComplete(err);
    2663           0 :             return;
    2664             :         }
    2665           0 :         break;
    2666             :     }
    2667           0 :     case CommissioningStage::kConfigureDSTOffset: {
    2668           0 :         if (!params.GetDSTOffsets().HasValue())
    2669             :         {
    2670           0 :             ChipLogError(Controller, "ConfigureDSTOffset stage called with no DST data");
    2671           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2672           0 :             return;
    2673             :         }
    2674           0 :         TimeSynchronization::Commands::SetDSTOffset::Type request;
    2675           0 :         request.DSTOffset = params.GetDSTOffsets().Value();
    2676           0 :         CHIP_ERROR err    = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
    2677           0 :         if (err != CHIP_NO_ERROR)
    2678             :         {
    2679             :             // We won't get any async callbacks here, so just complete our stage.
    2680           0 :             ChipLogError(Controller, "Failed to send SetDSTOffset command: %" CHIP_ERROR_FORMAT, err.Format());
    2681           0 :             CommissioningStageComplete(err);
    2682           0 :             return;
    2683             :         }
    2684           0 :         break;
    2685             :     }
    2686           0 :     case CommissioningStage::kConfigureDefaultNTP: {
    2687           0 :         if (!params.GetDefaultNTP().HasValue())
    2688             :         {
    2689           0 :             ChipLogError(Controller, "ConfigureDefaultNTP stage called with no default NTP data");
    2690           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2691           0 :             return;
    2692             :         }
    2693           0 :         TimeSynchronization::Commands::SetDefaultNTP::Type request;
    2694           0 :         request.defaultNTP = params.GetDefaultNTP().Value();
    2695           0 :         CHIP_ERROR err     = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
    2696           0 :         if (err != CHIP_NO_ERROR)
    2697             :         {
    2698             :             // We won't get any async callbacks here, so just complete our stage.
    2699           0 :             ChipLogError(Controller, "Failed to send SetDefaultNTP command: %" CHIP_ERROR_FORMAT, err.Format());
    2700           0 :             CommissioningStageComplete(err);
    2701           0 :             return;
    2702             :         }
    2703           0 :         break;
    2704           0 :     }
    2705           0 :     case CommissioningStage::kScanNetworks: {
    2706           0 :         NetworkCommissioning::Commands::ScanNetworks::Type request;
    2707           0 :         if (params.GetWiFiCredentials().HasValue())
    2708             :         {
    2709           0 :             request.ssid.Emplace(params.GetWiFiCredentials().Value().ssid);
    2710             :         }
    2711           0 :         request.breadcrumb.Emplace(breadcrumb);
    2712           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnScanNetworksResponse, OnScanNetworksFailure, endpoint, timeout);
    2713           0 :         if (err != CHIP_NO_ERROR)
    2714             :         {
    2715             :             // We won't get any async callbacks here, so just complete our stage.
    2716           0 :             ChipLogError(Controller, "Failed to send ScanNetworks command: %" CHIP_ERROR_FORMAT, err.Format());
    2717           0 :             CommissioningStageComplete(err);
    2718           0 :             return;
    2719             :         }
    2720           0 :         break;
    2721           0 :     }
    2722           0 :     case CommissioningStage::kNeedsNetworkCreds: {
    2723             :         // nothing to do, the OnScanNetworksSuccess and OnScanNetworksFailure callbacks provide indication to the
    2724             :         // DevicePairingDelegate that network credentials are needed.
    2725           0 :         break;
    2726             :     }
    2727           0 :     case CommissioningStage::kConfigRegulatory: {
    2728             :         // TODO(cecille): Worthwhile to keep this around as part of the class?
    2729             :         // TODO(cecille): Where is the country config actually set?
    2730           0 :         ChipLogProgress(Controller, "Setting Regulatory Config");
    2731             :         auto capability =
    2732           0 :             params.GetLocationCapability().ValueOr(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor);
    2733             :         app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum regulatoryConfig;
    2734             :         // Value is only switchable on the devices with indoor/outdoor capability
    2735           0 :         if (capability == app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kIndoorOutdoor)
    2736             :         {
    2737             :             // If the device supports indoor and outdoor configs, use the setting from the commissioner, otherwise fall back to
    2738             :             // the current device setting then to outdoor (most restrictive)
    2739           0 :             if (params.GetDeviceRegulatoryLocation().HasValue())
    2740             :             {
    2741           0 :                 regulatoryConfig = params.GetDeviceRegulatoryLocation().Value();
    2742           0 :                 ChipLogProgress(Controller, "Setting regulatory config to %u from commissioner override",
    2743             :                                 static_cast<uint8_t>(regulatoryConfig));
    2744             :             }
    2745           0 :             else if (params.GetDefaultRegulatoryLocation().HasValue())
    2746             :             {
    2747           0 :                 regulatoryConfig = params.GetDefaultRegulatoryLocation().Value();
    2748           0 :                 ChipLogProgress(Controller, "No regulatory config supplied by controller, leaving as device default (%u)",
    2749             :                                 static_cast<uint8_t>(regulatoryConfig));
    2750             :             }
    2751             :             else
    2752             :             {
    2753           0 :                 regulatoryConfig = app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor;
    2754           0 :                 ChipLogProgress(Controller, "No overrride or device regulatory config supplied, setting to outdoor");
    2755             :             }
    2756             :         }
    2757             :         else
    2758             :         {
    2759           0 :             ChipLogProgress(Controller, "Device does not support configurable regulatory location");
    2760           0 :             regulatoryConfig = capability;
    2761             :         }
    2762             : 
    2763           0 :         CharSpan countryCode;
    2764           0 :         const auto & providedCountryCode = params.GetCountryCode();
    2765           0 :         if (providedCountryCode.HasValue())
    2766             :         {
    2767           0 :             countryCode = providedCountryCode.Value();
    2768             :         }
    2769             :         else
    2770             :         {
    2771             :             // Default to "XX", for lack of anything better.
    2772           0 :             countryCode = "XX"_span;
    2773             :         }
    2774             : 
    2775           0 :         GeneralCommissioning::Commands::SetRegulatoryConfig::Type request;
    2776           0 :         request.newRegulatoryConfig = regulatoryConfig;
    2777           0 :         request.countryCode         = countryCode;
    2778           0 :         request.breadcrumb          = breadcrumb;
    2779           0 :         CHIP_ERROR err              = SendCommand(proxy, request, OnSetRegulatoryConfigResponse, OnBasicFailure, endpoint, timeout);
    2780           0 :         if (err != CHIP_NO_ERROR)
    2781             :         {
    2782             :             // We won't get any async callbacks here, so just complete our stage.
    2783           0 :             ChipLogError(Controller, "Failed to send SetRegulatoryConfig command: %" CHIP_ERROR_FORMAT, err.Format());
    2784           0 :             CommissioningStageComplete(err);
    2785           0 :             return;
    2786             :         }
    2787           0 :     }
    2788           0 :     break;
    2789           0 :     case CommissioningStage::kSendPAICertificateRequest: {
    2790           0 :         ChipLogProgress(Controller, "Sending request for PAI certificate");
    2791           0 :         CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kPAI, timeout);
    2792           0 :         if (err != CHIP_NO_ERROR)
    2793             :         {
    2794             :             // We won't get any async callbacks here, so just complete our stage.
    2795           0 :             ChipLogError(Controller, "Failed to send CertificateChainRequest command to get PAI: %" CHIP_ERROR_FORMAT,
    2796             :                          err.Format());
    2797           0 :             CommissioningStageComplete(err);
    2798           0 :             return;
    2799             :         }
    2800           0 :         break;
    2801             :     }
    2802           0 :     case CommissioningStage::kSendDACCertificateRequest: {
    2803           0 :         ChipLogProgress(Controller, "Sending request for DAC certificate");
    2804           0 :         CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kDAC, timeout);
    2805           0 :         if (err != CHIP_NO_ERROR)
    2806             :         {
    2807             :             // We won't get any async callbacks here, so just complete our stage.
    2808           0 :             ChipLogError(Controller, "Failed to send CertificateChainRequest command to get DAC: %" CHIP_ERROR_FORMAT,
    2809             :                          err.Format());
    2810           0 :             CommissioningStageComplete(err);
    2811           0 :             return;
    2812             :         }
    2813           0 :         break;
    2814             :     }
    2815           0 :     case CommissioningStage::kSendAttestationRequest: {
    2816           0 :         ChipLogProgress(Controller, "Sending Attestation Request to the device.");
    2817           0 :         if (!params.GetAttestationNonce().HasValue())
    2818             :         {
    2819           0 :             ChipLogError(Controller, "No attestation nonce found");
    2820           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2821           0 :             return;
    2822             :         }
    2823           0 :         CHIP_ERROR err = SendAttestationRequestCommand(proxy, params.GetAttestationNonce().Value(), timeout);
    2824           0 :         if (err != CHIP_NO_ERROR)
    2825             :         {
    2826             :             // We won't get any async callbacks here, so just complete our stage.
    2827           0 :             ChipLogError(Controller, "Failed to send AttestationRequest command: %" CHIP_ERROR_FORMAT, err.Format());
    2828           0 :             CommissioningStageComplete(err);
    2829           0 :             return;
    2830             :         }
    2831           0 :         break;
    2832             :     }
    2833           0 :     case CommissioningStage::kAttestationVerification: {
    2834           0 :         ChipLogProgress(Controller, "Verifying attestation");
    2835           0 :         if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
    2836           0 :             !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
    2837           0 :             !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
    2838             :         {
    2839           0 :             ChipLogError(Controller, "Missing attestation information");
    2840           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2841           0 :             return;
    2842             :         }
    2843             : 
    2844             :         DeviceAttestationVerifier::AttestationInfo info(
    2845           0 :             params.GetAttestationElements().Value(),
    2846           0 :             proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(),
    2847           0 :             params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(),
    2848           0 :             params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value());
    2849             : 
    2850           0 :         if (ValidateAttestationInfo(info) != CHIP_NO_ERROR)
    2851             :         {
    2852           0 :             ChipLogError(Controller, "Error validating attestation information");
    2853           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2854           0 :             return;
    2855             :         }
    2856             :     }
    2857           0 :     break;
    2858           0 :     case CommissioningStage::kSendOpCertSigningRequest: {
    2859           0 :         if (!params.GetCSRNonce().HasValue())
    2860             :         {
    2861           0 :             ChipLogError(Controller, "No CSR nonce found");
    2862           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2863           0 :             return;
    2864             :         }
    2865           0 :         CHIP_ERROR err = SendOperationalCertificateSigningRequestCommand(proxy, params.GetCSRNonce().Value(), timeout);
    2866           0 :         if (err != CHIP_NO_ERROR)
    2867             :         {
    2868             :             // We won't get any async callbacks here, so just complete our stage.
    2869           0 :             ChipLogError(Controller, "Failed to send CSR request: %" CHIP_ERROR_FORMAT, err.Format());
    2870           0 :             CommissioningStageComplete(err);
    2871           0 :             return;
    2872             :         }
    2873           0 :         break;
    2874             :     }
    2875           0 :     case CommissioningStage::kValidateCSR: {
    2876           0 :         if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetCSRNonce().HasValue())
    2877             :         {
    2878           0 :             ChipLogError(Controller, "Unable to validate CSR");
    2879           0 :             return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2880             :         }
    2881             :         // This is non-blocking, so send the callback immediately.
    2882           0 :         CHIP_ERROR err = ValidateCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
    2883           0 :                                      params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
    2884           0 :                                      params.GetCSRNonce().Value());
    2885           0 :         if (err != CHIP_NO_ERROR)
    2886             :         {
    2887           0 :             ChipLogError(Controller, "Unable to validate CSR");
    2888             :         }
    2889           0 :         CommissioningStageComplete(err);
    2890           0 :         return;
    2891             :     }
    2892             :     break;
    2893           0 :     case CommissioningStage::kGenerateNOCChain: {
    2894           0 :         if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
    2895           0 :             !params.GetCSRNonce().HasValue())
    2896             :         {
    2897           0 :             ChipLogError(Controller, "Unable to generate NOC chain parameters");
    2898           0 :             return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2899             :         }
    2900           0 :         CHIP_ERROR err = ProcessCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
    2901           0 :                                     params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
    2902           0 :                                     params.GetPAI().Value(), params.GetCSRNonce().Value());
    2903           0 :         if (err != CHIP_NO_ERROR)
    2904             :         {
    2905           0 :             ChipLogError(Controller, "Unable to process Op CSR");
    2906             :             // Handle error, and notify session failure to the commissioner application.
    2907           0 :             ChipLogError(Controller, "Failed to process the certificate signing request");
    2908             :             // TODO: Map error status to correct error code
    2909           0 :             CommissioningStageComplete(err);
    2910           0 :             return;
    2911             :         }
    2912             :     }
    2913           0 :     break;
    2914           0 :     case CommissioningStage::kSendTrustedRootCert: {
    2915           0 :         if (!params.GetRootCert().HasValue() || !params.GetNoc().HasValue())
    2916             :         {
    2917           0 :             ChipLogError(Controller, "No trusted root cert or NOC specified");
    2918           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2919           0 :             return;
    2920             :         }
    2921           0 :         CHIP_ERROR err = SendTrustedRootCertificate(proxy, params.GetRootCert().Value(), timeout);
    2922           0 :         if (err != CHIP_NO_ERROR)
    2923             :         {
    2924           0 :             ChipLogError(Controller, "Error sending trusted root certificate: %" CHIP_ERROR_FORMAT, err.Format());
    2925           0 :             CommissioningStageComplete(err);
    2926           0 :             return;
    2927             :         }
    2928             : 
    2929           0 :         err = proxy->SetPeerId(params.GetRootCert().Value(), params.GetNoc().Value());
    2930           0 :         if (err != CHIP_NO_ERROR)
    2931             :         {
    2932           0 :             ChipLogError(Controller, "Error setting peer id: %s", err.AsString());
    2933           0 :             CommissioningStageComplete(err);
    2934           0 :             return;
    2935             :         }
    2936           0 :         if (!IsOperationalNodeId(proxy->GetDeviceId()))
    2937             :         {
    2938           0 :             ChipLogError(Controller, "Given node ID is not an operational node ID");
    2939           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2940           0 :             return;
    2941             :         }
    2942             :     }
    2943           0 :     break;
    2944           0 :     case CommissioningStage::kSendNOC: {
    2945           0 :         if (!params.GetNoc().HasValue() || !params.GetIpk().HasValue() || !params.GetAdminSubject().HasValue())
    2946             :         {
    2947           0 :             ChipLogError(Controller, "AddNOC contents not specified");
    2948           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2949           0 :             return;
    2950             :         }
    2951           0 :         CHIP_ERROR err = SendOperationalCertificate(proxy, params.GetNoc().Value(), params.GetIcac(), params.GetIpk().Value(),
    2952           0 :                                                     params.GetAdminSubject().Value(), timeout);
    2953           0 :         if (err != CHIP_NO_ERROR)
    2954             :         {
    2955             :             // We won't get any async callbacks here, so just complete our stage.
    2956           0 :             ChipLogError(Controller, "Error sending operational certificate: %" CHIP_ERROR_FORMAT, err.Format());
    2957           0 :             CommissioningStageComplete(err);
    2958           0 :             return;
    2959             :         }
    2960           0 :         break;
    2961             :     }
    2962           0 :     case CommissioningStage::kConfigureTrustedTimeSource: {
    2963           0 :         if (!params.GetTrustedTimeSource().HasValue())
    2964             :         {
    2965           0 :             ChipLogError(Controller, "ConfigureTrustedTimeSource stage called with no trusted time source data");
    2966           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2967           0 :             return;
    2968             :         }
    2969           0 :         TimeSynchronization::Commands::SetTrustedTimeSource::Type request;
    2970           0 :         request.trustedTimeSource = params.GetTrustedTimeSource().Value();
    2971           0 :         CHIP_ERROR err            = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
    2972           0 :         if (err != CHIP_NO_ERROR)
    2973             :         {
    2974             :             // We won't get any async callbacks here, so just complete our stage.
    2975           0 :             ChipLogError(Controller, "Failed to send SendTrustedTimeSource command: %" CHIP_ERROR_FORMAT, err.Format());
    2976           0 :             CommissioningStageComplete(err);
    2977           0 :             return;
    2978             :         }
    2979           0 :         break;
    2980           0 :     }
    2981           0 :     case CommissioningStage::kWiFiNetworkSetup: {
    2982           0 :         if (!params.GetWiFiCredentials().HasValue())
    2983             :         {
    2984           0 :             ChipLogError(Controller, "No wifi credentials specified");
    2985           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    2986           0 :             return;
    2987             :         }
    2988             : 
    2989           0 :         NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type request;
    2990           0 :         request.ssid        = params.GetWiFiCredentials().Value().ssid;
    2991           0 :         request.credentials = params.GetWiFiCredentials().Value().credentials;
    2992           0 :         request.breadcrumb.Emplace(breadcrumb);
    2993           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
    2994           0 :         if (err != CHIP_NO_ERROR)
    2995             :         {
    2996             :             // We won't get any async callbacks here, so just complete our stage.
    2997           0 :             ChipLogError(Controller, "Failed to send AddOrUpdateWiFiNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
    2998           0 :             CommissioningStageComplete(err);
    2999           0 :             return;
    3000             :         }
    3001           0 :     }
    3002           0 :     break;
    3003           0 :     case CommissioningStage::kThreadNetworkSetup: {
    3004           0 :         if (!params.GetThreadOperationalDataset().HasValue())
    3005             :         {
    3006           0 :             ChipLogError(Controller, "No thread credentials specified");
    3007           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    3008           0 :             return;
    3009             :         }
    3010           0 :         NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type request;
    3011           0 :         request.operationalDataset = params.GetThreadOperationalDataset().Value();
    3012           0 :         request.breadcrumb.Emplace(breadcrumb);
    3013           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
    3014           0 :         if (err != CHIP_NO_ERROR)
    3015             :         {
    3016             :             // We won't get any async callbacks here, so just complete our stage.
    3017           0 :             ChipLogError(Controller, "Failed to send AddOrUpdateThreadNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
    3018           0 :             CommissioningStageComplete(err);
    3019           0 :             return;
    3020             :         }
    3021           0 :     }
    3022           0 :     break;
    3023           0 :     case CommissioningStage::kFailsafeBeforeWiFiEnable:
    3024             :         FALLTHROUGH;
    3025             :     case CommissioningStage::kFailsafeBeforeThreadEnable:
    3026             :         // Before we try to do network enablement, make sure that our fail-safe
    3027             :         // is set far enough out that we can later try to do operational
    3028             :         // discovery without it timing out.
    3029           0 :         ExtendFailsafeBeforeNetworkEnable(proxy, params, step);
    3030           0 :         break;
    3031           0 :     case CommissioningStage::kWiFiNetworkEnable: {
    3032           0 :         if (!params.GetWiFiCredentials().HasValue())
    3033             :         {
    3034           0 :             ChipLogError(Controller, "No wifi credentials specified");
    3035           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    3036           0 :             return;
    3037             :         }
    3038           0 :         NetworkCommissioning::Commands::ConnectNetwork::Type request;
    3039           0 :         request.networkID = params.GetWiFiCredentials().Value().ssid;
    3040           0 :         request.breadcrumb.Emplace(breadcrumb);
    3041             : 
    3042           0 :         CHIP_ERROR err = CHIP_NO_ERROR;
    3043           0 :         ChipLogProgress(Controller, "SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%d",
    3044             :                         params.GetSupportsConcurrentConnection().Value());
    3045           0 :         err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
    3046             : 
    3047           0 :         if (err != CHIP_NO_ERROR)
    3048             :         {
    3049             :             // We won't get any async callbacks here, so just complete our stage.
    3050           0 :             ChipLogError(Controller, "Failed to send WiFi ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
    3051           0 :             CommissioningStageComplete(err);
    3052           0 :             return;
    3053             :         }
    3054           0 :     }
    3055           0 :     break;
    3056           0 :     case CommissioningStage::kThreadNetworkEnable: {
    3057           0 :         ByteSpan extendedPanId;
    3058             :         chip::Thread::OperationalDataset operationalDataset;
    3059           0 :         if (!params.GetThreadOperationalDataset().HasValue() ||
    3060           0 :             operationalDataset.Init(params.GetThreadOperationalDataset().Value()) != CHIP_NO_ERROR ||
    3061           0 :             operationalDataset.GetExtendedPanIdAsByteSpan(extendedPanId) != CHIP_NO_ERROR)
    3062             :         {
    3063           0 :             ChipLogError(Controller, "Unable to get extended pan ID for thread operational dataset\n");
    3064           0 :             CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
    3065           0 :             return;
    3066             :         }
    3067           0 :         NetworkCommissioning::Commands::ConnectNetwork::Type request;
    3068           0 :         request.networkID = extendedPanId;
    3069           0 :         request.breadcrumb.Emplace(breadcrumb);
    3070           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
    3071           0 :         if (err != CHIP_NO_ERROR)
    3072             :         {
    3073             :             // We won't get any async callbacks here, so just complete our stage.
    3074           0 :             ChipLogError(Controller, "Failed to send Thread ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
    3075           0 :             CommissioningStageComplete(err);
    3076           0 :             return;
    3077             :         }
    3078           0 :     }
    3079           0 :     break;
    3080           0 :     case CommissioningStage::kICDGetRegistrationInfo: {
    3081           0 :         GetPairingDelegate()->OnICDRegistrationInfoRequired();
    3082           0 :         return;
    3083             :     }
    3084             :     break;
    3085           0 :     case CommissioningStage::kICDRegistration: {
    3086           0 :         IcdManagement::Commands::RegisterClient::Type request;
    3087             : 
    3088           0 :         if (!(params.GetICDCheckInNodeId().HasValue() && params.GetICDMonitoredSubject().HasValue() &&
    3089           0 :               params.GetICDSymmetricKey().HasValue()))
    3090             :         {
    3091           0 :             ChipLogError(Controller, "No ICD Registration information provided!");
    3092           0 :             CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE);
    3093           0 :             return;
    3094             :         }
    3095             : 
    3096           0 :         request.checkInNodeID    = params.GetICDCheckInNodeId().Value();
    3097           0 :         request.monitoredSubject = params.GetICDMonitoredSubject().Value();
    3098           0 :         request.key              = params.GetICDSymmetricKey().Value();
    3099             : 
    3100           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnICDManagementRegisterClientResponse, OnBasicFailure, endpoint, timeout);
    3101           0 :         if (err != CHIP_NO_ERROR)
    3102             :         {
    3103             :             // We won't get any async callbacks here, so just complete our stage.
    3104           0 :             ChipLogError(Controller, "Failed to send IcdManagement.RegisterClient command: %" CHIP_ERROR_FORMAT, err.Format());
    3105           0 :             CommissioningStageComplete(err);
    3106           0 :             return;
    3107             :         }
    3108           0 :     }
    3109           0 :     break;
    3110           0 :     case CommissioningStage::kICDSendStayActive: {
    3111             :         // TODO(#24259): Send StayActiveRequest once server supports this.
    3112           0 :         CommissioningStageComplete(CHIP_NO_ERROR);
    3113             :     }
    3114           0 :     break;
    3115           0 :     case CommissioningStage::kFindOperational: {
    3116             :         // If there is an error, CommissioningStageComplete will be called from OnDeviceConnectionFailureFn.
    3117           0 :         auto scopedPeerId = GetPeerScopedId(proxy->GetDeviceId());
    3118             : 
    3119             :         // If we ever had a commissioned device with this node ID before, we may
    3120             :         // have stale sessions to it.  Make sure we don't re-use any of those,
    3121             :         // because clearly they are not related to this new device we are
    3122             :         // commissioning.  We only care about sessions we might reuse, so just
    3123             :         // clearing the ones associated with our fabric index is good enough and
    3124             :         // we don't need to worry about ExpireAllSessionsOnLogicalFabric.
    3125           0 :         mSystemState->SessionMgr()->ExpireAllSessions(scopedPeerId);
    3126             : 
    3127           0 :         mSystemState->CASESessionMgr()->FindOrEstablishSession(scopedPeerId, &mOnDeviceConnectedCallback,
    3128             :                                                                &mOnDeviceConnectionFailureCallback
    3129             : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
    3130             :                                                                ,
    3131             :                                                                /* attemptCount = */ 3, &mOnDeviceConnectionRetryCallback
    3132             : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
    3133             :         );
    3134             :     }
    3135           0 :     break;
    3136           0 :     case CommissioningStage::kSendComplete: {
    3137             :         GeneralCommissioning::Commands::CommissioningComplete::Type request;
    3138           0 :         CHIP_ERROR err = SendCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout);
    3139           0 :         if (err != CHIP_NO_ERROR)
    3140             :         {
    3141             :             // We won't get any async callbacks here, so just complete our stage.
    3142           0 :             ChipLogError(Controller, "Failed to send CommissioningComplete command: %" CHIP_ERROR_FORMAT, err.Format());
    3143           0 :             CommissioningStageComplete(err);
    3144           0 :             return;
    3145             :         }
    3146             :     }
    3147           0 :     break;
    3148           0 :     case CommissioningStage::kCleanup:
    3149           0 :         CleanupCommissioning(proxy, proxy->GetDeviceId(), params.GetCompletionStatus());
    3150           0 :         break;
    3151           0 :     case CommissioningStage::kError:
    3152           0 :         mCommissioningStage = CommissioningStage::kSecurePairing;
    3153           0 :         break;
    3154           0 :     case CommissioningStage::kSecurePairing:
    3155           0 :         break;
    3156             :     }
    3157             : }
    3158             : 
    3159           0 : void DeviceCommissioner::ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params,
    3160             :                                                            CommissioningStage step)
    3161             : {
    3162           0 :     auto * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
    3163           0 :     if (device != commissioneeDevice)
    3164             :     {
    3165             :         // Not a commissionee device; just return.
    3166           0 :         ChipLogError(Controller, "Trying to extend fail-safe for an unknown commissionee with device id " ChipLogFormatX64,
    3167             :                      ChipLogValueX64(device->GetDeviceId()));
    3168           0 :         CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE, CommissioningDelegate::CommissioningReport());
    3169           0 :         return;
    3170             :     }
    3171             : 
    3172             :     // Try to make sure we have at least enough time for our expected
    3173             :     // commissioning bits plus the MRP retries for a Sigma1.
    3174           0 :     uint16_t failSafeTimeoutSecs = params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout);
    3175           0 :     auto sigma1Timeout           = CASESession::ComputeSigma1ResponseTimeout(commissioneeDevice->GetPairing().GetRemoteMRPConfig());
    3176           0 :     uint16_t sigma1TimeoutSecs   = std::chrono::duration_cast<System::Clock::Seconds16>(sigma1Timeout).count();
    3177           0 :     if (UINT16_MAX - failSafeTimeoutSecs < sigma1TimeoutSecs)
    3178             :     {
    3179           0 :         failSafeTimeoutSecs = UINT16_MAX;
    3180             :     }
    3181             :     else
    3182             :     {
    3183           0 :         failSafeTimeoutSecs = static_cast<uint16_t>(failSafeTimeoutSecs + sigma1TimeoutSecs);
    3184             :     }
    3185             : 
    3186             :     // A false return from ExtendArmFailSafe is fine; we don't want to make the
    3187             :     // fail-safe shorter here.
    3188           0 :     if (!ExtendArmFailSafe(commissioneeDevice, step, failSafeTimeoutSecs, MakeOptional(kMinimumCommissioningStepTimeout),
    3189             :                            OnArmFailSafe, OnBasicFailure))
    3190             :     {
    3191             :         // Just move on to the next step.
    3192           0 :         CommissioningStageComplete(CHIP_NO_ERROR, CommissioningDelegate::CommissioningReport());
    3193             :     }
    3194             : }
    3195             : 
    3196           0 : CHIP_ERROR DeviceController::GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const
    3197             : {
    3198           0 :     const auto * fabricInfo = GetFabricInfo();
    3199           0 :     VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
    3200           0 :     return fabricInfo->GetCompressedFabricIdBytes(outBytes);
    3201             : }
    3202             : 
    3203           0 : CHIP_ERROR DeviceController::GetRootPublicKey(Crypto::P256PublicKey & outRootPublicKey) const
    3204             : {
    3205           0 :     const auto * fabricTable = GetFabricTable();
    3206           0 :     VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INCORRECT_STATE);
    3207           0 :     return fabricTable->FetchRootPubkey(mFabricIndex, outRootPublicKey);
    3208             : }
    3209             : 
    3210             : } // namespace Controller
    3211             : } // namespace chip

Generated by: LCOV version 1.14