/* * * 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 #include #include #include #include namespace chip { namespace Controller { class DeviceCommissioner; class AutoCommissioner : public CommissioningDelegate { public: AutoCommissioner(); ~AutoCommissioner() override; CHIP_ERROR SetCommissioningParameters(const CommissioningParameters & params) override; const CommissioningParameters & GetCommissioningParameters() const override; void SetOperationalCredentialsDelegate(OperationalCredentialsDelegate * operationalCredentialsDelegate) override; CHIP_ERROR StartCommissioning(DeviceCommissioner * commissioner, CommissioneeDeviceProxy * proxy) override; void StopCommissioning() { mStopCommissioning = true; }; CHIP_ERROR CommissioningStepFinished(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report) override; ByteSpan GetAttestationElements() const { return ByteSpan(mAttestationElements, mAttestationElementsLen); } ByteSpan GetAttestationSignature() const { return ByteSpan(mAttestationSignature, mAttestationSignatureLen); } ByteSpan GetAttestationNonce() const { return ByteSpan(mAttestationNonce); } protected: CommissioningStage GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr); DeviceCommissioner * GetCommissioner() { return mCommissioner; } CHIP_ERROR PerformStep(CommissioningStage nextStage); CommissioneeDeviceProxy * GetCommissioneeDeviceProxy() { return mCommissioneeDeviceProxy; } /** * The device argument to GetCommandTimeout is the device whose session will * be used for sending the relevant command. */ Optional GetCommandTimeout(DeviceProxy * device, CommissioningStage stage) const; CommissioningParameters mParams = CommissioningParameters(); private: DeviceProxy * GetDeviceProxyForStep(CommissioningStage nextStage); // Adjust the failsafe timer if CommissioningDelegate GetCASEFailsafeTimerSeconds is set void SetCASEFailsafeTimerIfNeeded(); void ReleaseDAC(); void ReleasePAI(); CHIP_ERROR SetDAC(const ByteSpan & dac); CHIP_ERROR SetPAI(const ByteSpan & pai); ByteSpan GetDAC() const { return ByteSpan(mDAC, mDACLen); } ByteSpan GetPAI() const { return ByteSpan(mPAI, mPAILen); } CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, Crypto::IdentityProtectionKeySpan ipk, NodeId adminSubject); EndpointId GetEndpoint(const CommissioningStage & stage) const; CommissioningStage GetNextCommissioningStageInternal(CommissioningStage currentStage, CHIP_ERROR & lastErr); CHIP_ERROR VerifyICDRegistrationInfo(const CommissioningParameters & params); // Helper function to determine whether next stage should be kWiFiNetworkSetup, // kThreadNetworkSetup or kCleanup, depending whether network information has // been provided that matches the thread/wifi endpoint of the target. CommissioningStage GetNextCommissioningStageNetworkSetup(CommissioningStage currentStage, CHIP_ERROR & lastErr); // Helper function to determine if a scan attempt should be made given the // scan attempt commissioning params and the corresponding network endpoint of // the target. bool IsScanNeeded() { return ((mParams.GetAttemptWiFiNetworkScan().ValueOr(false) && mDeviceCommissioningInfo.network.wifi.endpoint != kInvalidEndpointId) || (mParams.GetAttemptThreadNetworkScan().ValueOr(false) && mDeviceCommissioningInfo.network.thread.endpoint != kInvalidEndpointId)); }; // Helper function to Determine whether secondary network interface is supported. // Only true if information is provided for both networks, and the target has endpoint // for wifi and thread. bool IsSecondaryNetworkSupported() const { return ((mParams.GetSupportsConcurrentConnection().ValueOr(false) && mParams.GetWiFiCredentials().HasValue() && mDeviceCommissioningInfo.network.wifi.endpoint != kInvalidEndpointId) && mParams.GetThreadOperationalDataset().HasValue() && mDeviceCommissioningInfo.network.thread.endpoint != kInvalidEndpointId); } void TrySecondaryNetwork() { mTryingSecondaryNetwork = true; } bool TryingSecondaryNetwork() const { return mTryingSecondaryNetwork; } void ResetTryingSecondaryNetwork() { mTryingSecondaryNetwork = false; } bool mTryingSecondaryNetwork = false; bool mStopCommissioning = false; DeviceCommissioner * mCommissioner = nullptr; CommissioneeDeviceProxy * mCommissioneeDeviceProxy = nullptr; OperationalCredentialsDelegate * mOperationalCredentialsDelegate = nullptr; OperationalDeviceProxy mOperationalDeviceProxy; // Memory space for the commisisoning parameters that come in as ByteSpans - the caller is not guaranteed to retain this memory uint8_t mSsid[CommissioningParameters::kMaxSsidLen]; uint8_t mCredentials[CommissioningParameters::kMaxCredentialsLen]; uint8_t mThreadOperationalDataset[CommissioningParameters::kMaxThreadDatasetLen]; char mCountryCode[CommissioningParameters::kMaxCountryCodeLen]; // Time zone is statically allocated because it is max 2 and not trivially destructible static constexpr size_t kMaxSupportedTimeZones = 2; app::Clusters::TimeSynchronization::Structs::TimeZoneStruct::Type mTimeZoneBuf[kMaxSupportedTimeZones]; static constexpr size_t kMaxTimeZoneNameLen = 64; char mTimeZoneNames[kMaxTimeZoneNameLen][kMaxSupportedTimeZones]; // DSTOffsetStructs are similarly not trivially destructible. They don't have a defined size, but we're // going to do static allocation of the buffers anyway until we replace chip::Optional with std::optional. static constexpr size_t kMaxSupportedDstStructs = 10; app::Clusters::TimeSynchronization::Structs::DSTOffsetStruct::Type mDstOffsetsBuf[kMaxSupportedDstStructs]; static constexpr size_t kMaxDefaultNtpSize = 128; char mDefaultNtp[kMaxDefaultNtpSize]; bool mNeedsNetworkSetup = false; ReadCommissioningInfo mDeviceCommissioningInfo; bool mNeedsDST = false; bool mNeedIcdRegistration = false; // TODO: Why were the nonces statically allocated, but the certs dynamically allocated? uint8_t * mDAC = nullptr; uint16_t mDACLen = 0; uint8_t * mPAI = nullptr; uint16_t mPAILen = 0; uint8_t mAttestationNonce[kAttestationNonceLength]; uint8_t mCSRNonce[kCSRNonceLength]; uint8_t mNOCertBuffer[Credentials::kMaxCHIPCertLength]; uint8_t mICACertBuffer[Credentials::kMaxCHIPCertLength]; uint16_t mAttestationElementsLen = 0; uint8_t mAttestationElements[Credentials::kMaxRspLen]; uint16_t mAttestationSignatureLen = 0; uint8_t mAttestationSignature[Crypto::kMax_ECDSA_Signature_Length]; uint8_t mICDSymmetricKey[Crypto::kAES_CCM128_Key_Length]; }; } // namespace Controller } // namespace chip