blob: deacda6e3cca3166024961c3ea7bf9f5870d5311 [file] [log] [blame]
/*
*
* 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 <controller/CommissioneeDeviceProxy.h>
#include <controller/CommissioningDelegate.h>
#include <credentials/DeviceAttestationConstructor.h>
#include <crypto/CHIPCryptoPAL.h>
#include <protocols/secure_channel/RendezvousParameters.h>
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<System::Clock::Timeout> 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