| /* | 
 |  * | 
 |  *    Copyright (c) 2021 Project CHIP Authors | 
 |  *    All rights reserved. | 
 |  * | 
 |  *    Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  *    you may not use this file except in compliance with the License. | 
 |  *    You may obtain a copy of the License at | 
 |  * | 
 |  *        http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  *    Unless required by applicable law or agreed to in writing, software | 
 |  *    distributed under the License is distributed on an "AS IS" BASIS, | 
 |  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  *    See the License for the specific language governing permissions and | 
 |  *    limitations under the License. | 
 |  */ | 
 |  | 
 | #pragma once | 
 | #include <app/OperationalSessionSetup.h> | 
 | #include <controller/CommissioneeDeviceProxy.h> | 
 | #include <credentials/attestation_verifier/DeviceAttestationDelegate.h> | 
 | #include <credentials/attestation_verifier/DeviceAttestationVerifier.h> | 
 | #include <lib/support/Variant.h> | 
 | #include <system/SystemClock.h> | 
 |  | 
 | namespace chip { | 
 | namespace Controller { | 
 |  | 
 | class DeviceCommissioner; | 
 |  | 
 | enum CommissioningStage : uint8_t | 
 | { | 
 |     kError, | 
 |     kSecurePairing,             ///< Establish a PASE session with the device | 
 |     kReadCommissioningInfo,     ///< Query General Commissioning Attributes and Network Features | 
 |     kArmFailsafe,               ///< Send ArmFailSafe (0x30:0) command to the device | 
 |     kConfigRegulatory,          ///< Send SetRegulatoryConfig (0x30:2) command to the device | 
 |     kSendPAICertificateRequest, ///< Send PAI CertificateChainRequest (0x3E:2) command to the device | 
 |     kSendDACCertificateRequest, ///< Send DAC CertificateChainRequest (0x3E:2) command to the device | 
 |     kSendAttestationRequest,    ///< Send AttestationRequest (0x3E:0) command to the device | 
 |     kAttestationVerification,   ///< Verify AttestationResponse (0x3E:1) validity | 
 |     kSendOpCertSigningRequest,  ///< Send CSRRequest (0x3E:4) command to the device | 
 |     kValidateCSR,               ///< Verify CSRResponse (0x3E:5) validity | 
 |     kGenerateNOCChain,          ///< TLV encode Node Operational Credentials (NOC) chain certs | 
 |     kSendTrustedRootCert,       ///< Send AddTrustedRootCertificate (0x3E:11) command to the device | 
 |     kSendNOC,                   ///< Send AddNOC (0x3E:6) command to the device | 
 |     kWiFiNetworkSetup,          ///< Send AddOrUpdateWiFiNetwork (0x31:2) command to the device | 
 |     kThreadNetworkSetup,        ///< Send AddOrUpdateThreadNetwork (0x31:3) command to the device | 
 |     kWiFiNetworkEnable,         ///< Send ConnectNetwork (0x31:6) command to the device for the WiFi network | 
 |     kThreadNetworkEnable,       ///< Send ConnectNetwork (0x31:6) command to the device for the Thread network | 
 |     kFindOperational,           ///< Perform operational discovery and establish a CASE session with the device | 
 |     kSendComplete,              ///< Send CommissioningComplete (0x30:4) command to the device | 
 |     kCleanup,                   ///< Call delegates with status, free memory, clear timers and state | 
 |     /// Send ScanNetworks (0x31:0) command to the device. | 
 |     /// ScanNetworks can happen anytime after kArmFailsafe. | 
 |     /// However, the cirque tests fail if it is earlier in the list | 
 |     kScanNetworks, | 
 |     /// Waiting for the higher layer to provide network credentials before continuing the workflow. | 
 |     /// Call CHIPDeviceController::NetworkCredentialsReady() when CommissioningParameters is populated with | 
 |     /// network credentials to use in kWiFiNetworkSetup or kThreadNetworkSetup steps. | 
 |     kNeedsNetworkCreds, | 
 | }; | 
 |  | 
 | const char * StageToString(CommissioningStage stage); | 
 |  | 
 | struct WiFiCredentials | 
 | { | 
 |     ByteSpan ssid; | 
 |     ByteSpan credentials; | 
 |     WiFiCredentials(ByteSpan newSsid, ByteSpan newCreds) : ssid(newSsid), credentials(newCreds) {} | 
 | }; | 
 |  | 
 | struct NOCChainGenerationParameters | 
 | { | 
 |     ByteSpan nocsrElements; | 
 |     ByteSpan signature; | 
 | }; | 
 |  | 
 | struct CompletionStatus | 
 | { | 
 |     CompletionStatus() : err(CHIP_NO_ERROR), failedStage(NullOptional), attestationResult(NullOptional) {} | 
 |     CHIP_ERROR err; | 
 |     Optional<CommissioningStage> failedStage; | 
 |     Optional<Credentials::AttestationVerificationResult> attestationResult; | 
 |     Optional<app::Clusters::GeneralCommissioning::CommissioningError> commissioningError; | 
 |     Optional<app::Clusters::NetworkCommissioning::NetworkCommissioningStatus> networkCommissioningStatus; | 
 | }; | 
 |  | 
 | constexpr uint16_t kDefaultFailsafeTimeout = 60; | 
 |  | 
 | // Per spec, all commands that are sent with the failsafe armed need at least | 
 | // a 30s timeout. | 
 | constexpr System::Clock::Timeout kMinimumCommissioningStepTimeout = System::Clock::Seconds16(30); | 
 |  | 
 | class CommissioningParameters | 
 | { | 
 | public: | 
 |     static constexpr size_t kMaxThreadDatasetLen = 254; | 
 |     static constexpr size_t kMaxSsidLen          = 32; | 
 |     static constexpr size_t kMaxCredentialsLen   = 64; | 
 |     static constexpr size_t kMaxCountryCodeLen   = 2; | 
 |  | 
 |     // Value to use when setting the commissioning failsafe timer on the node being commissioned. | 
 |     // If the failsafe timer value is passed in as part of the commissioning parameters, that value will be used. If not supplied, | 
 |     // the AutoCommissioner will set this to the recommended value read from the node. If that is not set, it will fall back to the | 
 |     // default kDefaultFailsafeTimeout. | 
 |     // This value should be set before running PerformCommissioningStep for the kArmFailsafe step. | 
 |     const Optional<uint16_t> GetFailsafeTimerSeconds() const { return mFailsafeTimerSeconds; } | 
 |  | 
 |     // Value to use when re-setting the commissioning failsafe timer immediately prior to operational discovery. | 
 |     // If a CASE failsafe timer value is passed in as part of the commissioning parameters, then the failsafe timer | 
 |     // will be reset using this value before operational discovery begins. If not supplied, then the AutoCommissioner | 
 |     // will not automatically reset the failsafe timer before operational discovery begins. It can be useful for the | 
 |     // commissioner to set the CASE failsafe timer to a small value (ex. 30s) when the regular failsafe timer is set | 
 |     // to a larger value to accommodate user interaction during setup (network credential selection, user consent | 
 |     // after device attestation). | 
 |     const Optional<uint16_t> GetCASEFailsafeTimerSeconds() const { return mCASEFailsafeTimerSeconds; } | 
 |  | 
 |     // The location (indoor/outdoor) of the node being commissioned. | 
 |     // The node regulartory location (indoor/outdoor) should be set by the commissioner explicitly as it may be different than the | 
 |     // location of the commissioner. This location will be set on the node if the node supports configurable regulatory location | 
 |     // (from GetLocationCapability - see below). If the regulatory location is not supplied, this will fall back to the location in | 
 |     // GetDefaultRegulatoryLocation and then to Outdoor (most restrictive). | 
 |     // This value should be set before calling PerformCommissioningStep for the kConfigRegulatory step. | 
 |     const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> GetDeviceRegulatoryLocation() const | 
 |     { | 
 |         return mDeviceRegulatoryLocation; | 
 |     } | 
 |  | 
 |     // The country code to be used for the node, if set. | 
 |     Optional<CharSpan> GetCountryCode() const { return mCountryCode; } | 
 |  | 
 |     // Nonce sent to the node to use during the CSR request. | 
 |     // When using the AutoCommissioner, this value will be ignored in favour of the value supplied by the | 
 |     // OperationalCredentialsDelegate ObtainCsrNonce function. If the credential delegate is not supplied, the value supplied here | 
 |     // will be used. If neither is supplied random value will be used as a fallback. | 
 |     // This value must be set before calling PerformCommissioningStep for the kSendOpCertSigningRequest step. | 
 |     const Optional<ByteSpan> GetCSRNonce() const { return mCSRNonce; } | 
 |  | 
 |     // Nonce value sent to the node to use during the attestation request. | 
 |     // When using the AutoCommissioner, this value will fall back to random if not supplied. | 
 |     // If a non-random value is to be used, the value must be set before calling PerformCommissioningStep for the | 
 |     // kSendAttestationRequest step. | 
 |     const Optional<ByteSpan> GetAttestationNonce() const { return mAttestationNonce; } | 
 |  | 
 |     // WiFi SSID and credentials to use when adding/updating and enabling WiFi on the node. | 
 |     // This value must be set before calling PerformCommissioningStep for the kWiFiNetworkSetup or kWiFiNetworkEnable steps. | 
 |     const Optional<WiFiCredentials> GetWiFiCredentials() const { return mWiFiCreds; } | 
 |  | 
 |     // Thread operational dataset to use when adding/updating and enabling the thread network on the node. | 
 |     // This value must be set before calling PerformCommissioningStep for the kThreadNetworkSetup or kThreadNetworkEnable steps. | 
 |     const Optional<ByteSpan> GetThreadOperationalDataset() const { return mThreadOperationalDataset; } | 
 |  | 
 |     // The NOCSR parameters (elements and signature) returned from the node. In the AutoCommissioner, this is set using the data | 
 |     // returned from the kSendOpCertSigningRequest stage. | 
 |     // This value must be set before calling PerformCommissioningStep for the kGenerateNOCChain step. | 
 |     const Optional<NOCChainGenerationParameters> GetNOCChainGenerationParameters() const { return mNOCChainGenerationParameters; } | 
 |  | 
 |     // The root certificate for the operational certificate chain. In the auto commissioner, this is set by by the kGenerateNOCChain | 
 |     // stage through the OperationalCredentialsDelegate. | 
 |     // This value must be set before calling PerformCommissioningStep for the kSendTrustedRootCert step. | 
 |     const Optional<ByteSpan> GetRootCert() const { return mRootCert; } | 
 |  | 
 |     // The node operational certificate for the node being commissioned. In the AutoCommissioner, this is set by by the | 
 |     // kGenerateNOCChain stage through the OperationalCredentialsDelegate. | 
 |     // This value must be set before calling PerformCommissioningStep for the kSendNOC step. | 
 |     // This value must also be set before calling PerformCommissioningStep for the kSendTrustedRootCert step, as it is used to set | 
 |     // the node id in the DeviceProxy. | 
 |     const Optional<ByteSpan> GetNoc() const { return mNoc; } | 
 |  | 
 |     // The intermediate certificate for the node being commissioned. In the AutoCommissioner, this is set by by the | 
 |     // kGenerateNOCChain stage through the OperationalCredentialsDelegate. | 
 |     // This value should be set before calling PerformCommissioningStep for the kSendNOC step. | 
 |     const Optional<ByteSpan> GetIcac() const { return mIcac; } | 
 |  | 
 |     // Epoch key for the identity protection key for the node being commissioned. In the AutoCommissioner, this is set by by the | 
 |     // kGenerateNOCChain stage through the OperationalCredentialsDelegate. | 
 |     // This value must be set before calling PerformCommissioningStep for the kSendNOC step. | 
 |     const Optional<IdentityProtectionKeySpan> GetIpk() const | 
 |     { | 
 |         return mIpk.HasValue() ? Optional<IdentityProtectionKeySpan>(mIpk.Value().Span()) : Optional<IdentityProtectionKeySpan>(); | 
 |     } | 
 |  | 
 |     // Admin subject id used for the case access control entry created if the AddNOC command succeeds. In the AutoCommissioner, this | 
 |     // is set by by the kGenerateNOCChain stage through the OperationalCredentialsDelegate. | 
 |     // This must be set before calling PerformCommissioningStep for the kSendNOC step. | 
 |     const Optional<NodeId> GetAdminSubject() const { return mAdminSubject; } | 
 |  | 
 |     // Attestation elements from the node. These are obtained from node in response to the AttestationRequest command. In the | 
 |     // AutoCommissioner, this is automatically set from the report from the kSendAttestationRequest stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerification step. | 
 |     const Optional<ByteSpan> GetAttestationElements() const { return mAttestationElements; } | 
 |  | 
 |     // Attestation signature from the node. This is obtained from node in response to the AttestationRequest command. In the | 
 |     // AutoCommissioner, this is automatically set from the report from the kSendAttestationRequest stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerification step. | 
 |     const Optional<ByteSpan> GetAttestationSignature() const { return mAttestationSignature; } | 
 |  | 
 |     // Product attestation intermediate certificate from the node. This is obtained from the node in response to the | 
 |     // CertificateChainRequest command for the PAI. In the AutoCommissioner, this is automatically set from the report from the | 
 |     // kSendPAICertificateRequest stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerificationstep. | 
 |     const Optional<ByteSpan> GetPAI() const { return mPAI; } | 
 |  | 
 |     // Device attestation certificate from the node. This is obtained from the node in response to the CertificateChainRequest | 
 |     // command for the DAC. In the AutoCommissioner, this is automatically set from the report from the kSendDACCertificateRequest | 
 |     // stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerification step. | 
 |     const Optional<ByteSpan> GetDAC() const { return mDAC; } | 
 |  | 
 |     // Node ID when a matching fabric is found in the Node Operational Credentials cluster. | 
 |     // In the AutoCommissioner, this is set from kReadCommissioningInfo stage. | 
 |     const Optional<NodeId> GetRemoteNodeId() const { return mRemoteNodeId; } | 
 |  | 
 |     // Node vendor ID from the basic information cluster. In the AutoCommissioner, this is automatically set from report from the | 
 |     // kReadCommissioningInfo stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerification step. | 
 |     const Optional<VendorId> GetRemoteVendorId() const { return mRemoteVendorId; } | 
 |  | 
 |     // Node product ID from the basic information cluster. In the AutoCommissioner, this is automatically set from report from the | 
 |     // kReadCommissioningInfo stage. | 
 |     // This must be set before calling PerformCommissioningStep for the kAttestationVerification step. | 
 |     const Optional<uint16_t> GetRemoteProductId() const { return mRemoteProductId; } | 
 |  | 
 |     // Default regulatory location set by the node, as read from the GeneralCommissioning cluster. In the AutoCommissioner, this is | 
 |     // automatically set from report from the kReadCommissioningInfo stage. | 
 |     // This should be set before calling PerformCommissioningStep for the kConfigRegulatory step. | 
 |     const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> GetDefaultRegulatoryLocation() const | 
 |     { | 
 |         return mDefaultRegulatoryLocation; | 
 |     } | 
 |  | 
 |     // Location capabilities of the node, as read from the GeneralCommissioning cluster. In the AutoCommissioner, this is | 
 |     // automatically set from report from the kReadCommissioningInfo stage. | 
 |     // This should be set before calling PerformCommissioningStep for the kConfigRegulatory step. | 
 |     const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> GetLocationCapability() const | 
 |     { | 
 |         return mLocationCapability; | 
 |     } | 
 |  | 
 |     // Status to send when calling CommissioningComplete on the PairingDelegate during the kCleanup step. The AutoCommissioner uses | 
 |     // this to pass through any error messages received during commissioning. | 
 |     const CompletionStatus & GetCompletionStatus() const { return completionStatus; } | 
 |  | 
 |     CommissioningParameters & SetFailsafeTimerSeconds(uint16_t seconds) | 
 |     { | 
 |         mFailsafeTimerSeconds.SetValue(seconds); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     CommissioningParameters & SetCASEFailsafeTimerSeconds(uint16_t seconds) | 
 |     { | 
 |         mCASEFailsafeTimerSeconds.SetValue(seconds); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     CommissioningParameters & SetDeviceRegulatoryLocation(app::Clusters::GeneralCommissioning::RegulatoryLocationType location) | 
 |     { | 
 |         mDeviceRegulatoryLocation.SetValue(location); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // The lifetime of the buffer countryCode is pointing to should exceed the | 
 |     // lifetime of CommissioningParameters object. | 
 |     CommissioningParameters & SetCountryCode(CharSpan countryCode) | 
 |     { | 
 |         mCountryCode.SetValue(countryCode); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // The lifetime of the buffer csrNonce is pointing to, should exceed the lifetime of CommissioningParameters object. | 
 |     CommissioningParameters & SetCSRNonce(ByteSpan csrNonce) | 
 |     { | 
 |         mCSRNonce.SetValue(csrNonce); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // The lifetime of the buffer attestationNonce is pointing to, should exceed the lifetime of CommissioningParameters object. | 
 |     CommissioningParameters & SetAttestationNonce(ByteSpan attestationNonce) | 
 |     { | 
 |         mAttestationNonce.SetValue(attestationNonce); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetWiFiCredentials(WiFiCredentials wifiCreds) | 
 |     { | 
 |         mWiFiCreds.SetValue(wifiCreds); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // If a ThreadOperationalDataset is provided, then the ThreadNetworkScan will not be attempted | 
 |     CommissioningParameters & SetThreadOperationalDataset(ByteSpan threadOperationalDataset) | 
 |     { | 
 |  | 
 |         mThreadOperationalDataset.SetValue(threadOperationalDataset); | 
 |         mAttemptThreadNetworkScan = MakeOptional(static_cast<bool>(false)); | 
 |         return *this; | 
 |     } | 
 |     // This parameter should be set with the information returned from kSendOpCertSigningRequest. It must be set before calling | 
 |     // kGenerateNOCChain. | 
 |     CommissioningParameters & SetNOCChainGenerationParameters(const NOCChainGenerationParameters & params) | 
 |     { | 
 |         mNOCChainGenerationParameters.SetValue(params); | 
 |         return *this; | 
 |     } | 
 |     // Root certs can be generated from the kGenerateNOCChain step. This must be set before calling kSendTrustedRootCert. | 
 |     CommissioningParameters & SetRootCert(const ByteSpan & rcac) | 
 |     { | 
 |         mRootCert.SetValue(rcac); | 
 |         return *this; | 
 |     } | 
 |     // NOC and intermediate cert can be generated from the kGenerateNOCChain step. NOC must be set before calling | 
 |     // kSendTrustedRootCert. ICAC and NOC must be set before calling kSendNOC | 
 |     CommissioningParameters & SetNoc(const ByteSpan & noc) | 
 |     { | 
 |         mNoc.SetValue(noc); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetIcac(const ByteSpan & icac) | 
 |     { | 
 |         mIcac.SetValue(icac); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetIpk(const IdentityProtectionKeySpan ipk) | 
 |     { | 
 |         mIpk.SetValue(IdentityProtectionKey(ipk)); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetAdminSubject(const NodeId adminSubject) | 
 |     { | 
 |         mAdminSubject.SetValue(adminSubject); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetAttestationElements(const ByteSpan & attestationElements) | 
 |     { | 
 |         mAttestationElements = MakeOptional(attestationElements); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetAttestationSignature(const ByteSpan & attestationSignature) | 
 |     { | 
 |         mAttestationSignature = MakeOptional(attestationSignature); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetPAI(const ByteSpan & pai) | 
 |     { | 
 |         mPAI = MakeOptional(pai); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetDAC(const ByteSpan & dac) | 
 |     { | 
 |         mDAC = MakeOptional(dac); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetRemoteNodeId(NodeId id) | 
 |     { | 
 |         mRemoteNodeId = MakeOptional(id); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetRemoteVendorId(VendorId id) | 
 |     { | 
 |         mRemoteVendorId = MakeOptional(id); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetRemoteProductId(uint16_t id) | 
 |     { | 
 |         mRemoteProductId = MakeOptional(id); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetDefaultRegulatoryLocation(app::Clusters::GeneralCommissioning::RegulatoryLocationType location) | 
 |     { | 
 |         mDefaultRegulatoryLocation = MakeOptional(location); | 
 |         return *this; | 
 |     } | 
 |     CommissioningParameters & SetLocationCapability(app::Clusters::GeneralCommissioning::RegulatoryLocationType capability) | 
 |     { | 
 |         mLocationCapability = MakeOptional(capability); | 
 |         return *this; | 
 |     } | 
 |     void SetCompletionStatus(const CompletionStatus & status) { completionStatus = status; } | 
 |  | 
 |     CommissioningParameters & SetDeviceAttestationDelegate(Credentials::DeviceAttestationDelegate * deviceAttestationDelegate) | 
 |     { | 
 |         mDeviceAttestationDelegate = deviceAttestationDelegate; | 
 |         return *this; | 
 |     } | 
 |  | 
 |     Credentials::DeviceAttestationDelegate * GetDeviceAttestationDelegate() const { return mDeviceAttestationDelegate; } | 
 |  | 
 |     // If an SSID is provided, and AttemptWiFiNetworkScan is true, | 
 |     // then a directed scan will be performed using the SSID provided in the WiFiCredentials object | 
 |     Optional<bool> GetAttemptWiFiNetworkScan() const { return mAttemptWiFiNetworkScan; } | 
 |     CommissioningParameters & SetAttemptWiFiNetworkScan(bool attemptWiFiNetworkScan) | 
 |     { | 
 |         mAttemptWiFiNetworkScan = MakeOptional(attemptWiFiNetworkScan); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // If a ThreadOperationalDataset is provided, then the ThreadNetworkScan will not be attempted | 
 |     Optional<bool> GetAttemptThreadNetworkScan() const { return mAttemptThreadNetworkScan; } | 
 |     CommissioningParameters & SetAttemptThreadNetworkScan(bool attemptThreadNetworkScan) | 
 |     { | 
 |         if (!mThreadOperationalDataset.HasValue()) | 
 |         { | 
 |             mAttemptThreadNetworkScan = MakeOptional(attemptThreadNetworkScan); | 
 |         } | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // Only perform the PASE steps of commissioning. | 
 |     // Commissioning will be completed by another admin on the network. | 
 |     Optional<bool> GetSkipCommissioningComplete() const { return mSkipCommissioningComplete; } | 
 |     CommissioningParameters & SetSkipCommissioningComplete(bool skipCommissioningComplete) | 
 |     { | 
 |         mSkipCommissioningComplete = MakeOptional(skipCommissioningComplete); | 
 |         return *this; | 
 |     } | 
 |  | 
 |     // Check for matching fabric on target device by reading fabric list and looking for a | 
 |     // fabricId and RootCert match. If a match is detected, then use GetNodeId() to | 
 |     // access the nodeId for the device on the matching fabric. | 
 |     bool GetCheckForMatchingFabric() const { return mCheckForMatchingFabric; } | 
 |     CommissioningParameters & SetCheckForMatchingFabric(bool checkForMatchingFabric) | 
 |     { | 
 |         mCheckForMatchingFabric = checkForMatchingFabric; | 
 |         return *this; | 
 |     } | 
 |  | 
 | private: | 
 |     // Items that can be set by the commissioner | 
 |     Optional<uint16_t> mFailsafeTimerSeconds; | 
 |     Optional<uint16_t> mCASEFailsafeTimerSeconds; | 
 |     Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> mDeviceRegulatoryLocation; | 
 |     Optional<ByteSpan> mCSRNonce; | 
 |     Optional<ByteSpan> mAttestationNonce; | 
 |     Optional<WiFiCredentials> mWiFiCreds; | 
 |     Optional<CharSpan> mCountryCode; | 
 |     Optional<ByteSpan> mThreadOperationalDataset; | 
 |     Optional<NOCChainGenerationParameters> mNOCChainGenerationParameters; | 
 |     Optional<ByteSpan> mRootCert; | 
 |     Optional<ByteSpan> mNoc; | 
 |     Optional<ByteSpan> mIcac; | 
 |     Optional<IdentityProtectionKey> mIpk; | 
 |     Optional<NodeId> mAdminSubject; | 
 |     // Items that come from the device in commissioning steps | 
 |     Optional<ByteSpan> mAttestationElements; | 
 |     Optional<ByteSpan> mAttestationSignature; | 
 |     Optional<ByteSpan> mPAI; | 
 |     Optional<ByteSpan> mDAC; | 
 |     Optional<NodeId> mRemoteNodeId; | 
 |     Optional<VendorId> mRemoteVendorId; | 
 |     Optional<uint16_t> mRemoteProductId; | 
 |     Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> mDefaultRegulatoryLocation; | 
 |     Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationType> mLocationCapability; | 
 |     CompletionStatus completionStatus; | 
 |     Credentials::DeviceAttestationDelegate * mDeviceAttestationDelegate = | 
 |         nullptr; // Delegate to handle device attestation failures during commissioning | 
 |     Optional<bool> mAttemptWiFiNetworkScan; | 
 |     Optional<bool> mAttemptThreadNetworkScan; // This automatically gets set to false when a ThreadOperationalDataset is set | 
 |     Optional<bool> mSkipCommissioningComplete; | 
 |     bool mCheckForMatchingFabric = false; | 
 | }; | 
 |  | 
 | struct RequestedCertificate | 
 | { | 
 |     RequestedCertificate(ByteSpan newCertificate) : certificate(newCertificate) {} | 
 |     ByteSpan certificate; | 
 | }; | 
 |  | 
 | struct AttestationResponse | 
 | { | 
 |     AttestationResponse(ByteSpan newAttestationElements, ByteSpan newSignature) : | 
 |         attestationElements(newAttestationElements), signature(newSignature) | 
 |     {} | 
 |     ByteSpan attestationElements; | 
 |     ByteSpan signature; | 
 | }; | 
 |  | 
 | struct CSRResponse | 
 | { | 
 |     CSRResponse(ByteSpan elements, ByteSpan newSignature) : nocsrElements(elements), signature(newSignature) {} | 
 |     ByteSpan nocsrElements; | 
 |     ByteSpan signature; | 
 | }; | 
 |  | 
 | struct NocChain | 
 | { | 
 |     NocChain(ByteSpan newNoc, ByteSpan newIcac, ByteSpan newRcac, IdentityProtectionKeySpan newIpk, NodeId newAdminSubject) : | 
 |         noc(newNoc), icac(newIcac), rcac(newRcac), ipk(newIpk), adminSubject(newAdminSubject) | 
 |     {} | 
 |     ByteSpan noc; | 
 |     ByteSpan icac; | 
 |     ByteSpan rcac; | 
 |     IdentityProtectionKeySpan ipk; | 
 |     NodeId adminSubject; | 
 | }; | 
 |  | 
 | struct OperationalNodeFoundData | 
 | { | 
 |     OperationalNodeFoundData(OperationalDeviceProxy proxy) : operationalProxy(proxy) {} | 
 |     OperationalDeviceProxy operationalProxy; | 
 | }; | 
 |  | 
 | struct NetworkClusterInfo | 
 | { | 
 |     EndpointId endpoint = kInvalidEndpointId; | 
 |     app::Clusters::NetworkCommissioning::Attributes::ConnectMaxTimeSeconds::TypeInfo::DecodableType minConnectionTime; | 
 | }; | 
 | struct NetworkClusters | 
 | { | 
 |     NetworkClusterInfo wifi; | 
 |     NetworkClusterInfo thread; | 
 |     NetworkClusterInfo eth; | 
 | }; | 
 | struct BasicClusterInfo | 
 | { | 
 |     VendorId vendorId  = VendorId::Common; | 
 |     uint16_t productId = 0; | 
 | }; | 
 | struct GeneralCommissioningInfo | 
 | { | 
 |     uint64_t breadcrumb          = 0; | 
 |     uint16_t recommendedFailsafe = 0; | 
 |     app::Clusters::GeneralCommissioning::RegulatoryLocationType currentRegulatoryLocation = | 
 |         app::Clusters::GeneralCommissioning::RegulatoryLocationType::kIndoorOutdoor; | 
 |     app::Clusters::GeneralCommissioning::RegulatoryLocationType locationCapability = | 
 |         app::Clusters::GeneralCommissioning::RegulatoryLocationType::kIndoorOutdoor; | 
 |     ; | 
 | }; | 
 |  | 
 | struct ReadCommissioningInfo | 
 | { | 
 |     NetworkClusters network; | 
 |     BasicClusterInfo basic; | 
 |     GeneralCommissioningInfo general; | 
 |     NodeId nodeId = kUndefinedNodeId; | 
 | }; | 
 |  | 
 | struct AttestationErrorInfo | 
 | { | 
 |     AttestationErrorInfo(Credentials::AttestationVerificationResult result) : attestationResult(result) {} | 
 |     Credentials::AttestationVerificationResult attestationResult; | 
 | }; | 
 |  | 
 | struct CommissioningErrorInfo | 
 | { | 
 |     CommissioningErrorInfo(app::Clusters::GeneralCommissioning::CommissioningError result) : commissioningError(result) {} | 
 |     app::Clusters::GeneralCommissioning::CommissioningError commissioningError; | 
 | }; | 
 |  | 
 | struct NetworkCommissioningStatusInfo | 
 | { | 
 |     NetworkCommissioningStatusInfo(app::Clusters::NetworkCommissioning::NetworkCommissioningStatus result) : | 
 |         networkCommissioningStatus(result) | 
 |     {} | 
 |     app::Clusters::NetworkCommissioning::NetworkCommissioningStatus networkCommissioningStatus; | 
 | }; | 
 |  | 
 | class CommissioningDelegate | 
 | { | 
 | public: | 
 |     virtual ~CommissioningDelegate(){}; | 
 |     /* CommissioningReport is returned after each commissioning step is completed. The reports for each step are: | 
 |      * kReadCommissioningInfo - ReadCommissioningInfo | 
 |      * kArmFailsafe: CommissioningErrorInfo if there is an error | 
 |      * kConfigRegulatory: CommissioningErrorInfo if there is an error | 
 |      * kSendPAICertificateRequest: RequestedCertificate | 
 |      * kSendDACCertificateRequest: RequestedCertificate | 
 |      * kSendAttestationRequest: AttestationResponse | 
 |      * kAttestationVerification: AttestationErrorInfo if there is an error | 
 |      * kSendOpCertSigningRequest: CSRResponse | 
 |      * kGenerateNOCChain: NocChain | 
 |      * kSendTrustedRootCert: None | 
 |      * kSendNOC: none | 
 |      * kWiFiNetworkSetup: NetworkCommissioningStatusInfo if there is an error | 
 |      * kThreadNetworkSetup: NetworkCommissioningStatusInfo if there is an error | 
 |      * kWiFiNetworkEnable: NetworkCommissioningStatusInfo if there is an error | 
 |      * kThreadNetworkEnable: NetworkCommissioningStatusInfo if there is an error | 
 |      * kFindOperational: OperationalNodeFoundData | 
 |      * kSendComplete: CommissioningErrorInfo if there is an error | 
 |      * kCleanup: none | 
 |      */ | 
 |     struct CommissioningReport | 
 |         : Variant<RequestedCertificate, AttestationResponse, CSRResponse, NocChain, OperationalNodeFoundData, ReadCommissioningInfo, | 
 |                   AttestationErrorInfo, CommissioningErrorInfo, NetworkCommissioningStatusInfo> | 
 |     { | 
 |         CommissioningReport() : stageCompleted(CommissioningStage::kError) {} | 
 |         CommissioningStage stageCompleted; | 
 |     }; | 
 |     virtual CHIP_ERROR SetCommissioningParameters(const CommissioningParameters & params)                           = 0; | 
 |     virtual const CommissioningParameters & GetCommissioningParameters() const                                      = 0; | 
 |     virtual void SetOperationalCredentialsDelegate(OperationalCredentialsDelegate * operationalCredentialsDelegate) = 0; | 
 |     virtual CHIP_ERROR StartCommissioning(DeviceCommissioner * commissioner, CommissioneeDeviceProxy * proxy)       = 0; | 
 |     virtual CHIP_ERROR CommissioningStepFinished(CHIP_ERROR err, CommissioningReport report)                        = 0; | 
 | }; | 
 |  | 
 | } // namespace Controller | 
 | } // namespace chip |