Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #pragma once
19 :
20 : #include <app/AttributePathParams.h>
21 : #include <controller/CommissioneeDeviceProxy.h>
22 : #include <controller/CommissioningDelegate.h>
23 : #include <credentials/DeviceAttestationConstructor.h>
24 : #include <crypto/CHIPCryptoPAL.h>
25 : #include <lib/support/ScopedBuffer.h>
26 : #include <protocols/secure_channel/RendezvousParameters.h>
27 :
28 : namespace chip {
29 :
30 : namespace Testing {
31 :
32 : class AutoCommissionerTestAccess;
33 :
34 : } // namespace Testing
35 :
36 : namespace Controller {
37 :
38 : class DeviceCommissioner;
39 :
40 : class AutoCommissioner : public CommissioningDelegate
41 : {
42 :
43 : friend class chip::Testing::AutoCommissionerTestAccess;
44 :
45 : public:
46 : AutoCommissioner();
47 : ~AutoCommissioner() override;
48 : CHIP_ERROR SetCommissioningParameters(const CommissioningParameters & params) override;
49 : const CommissioningParameters & GetCommissioningParameters() const override;
50 : void SetOperationalCredentialsDelegate(OperationalCredentialsDelegate * operationalCredentialsDelegate) override;
51 :
52 : CHIP_ERROR StartCommissioning(DeviceCommissioner * commissioner, CommissioneeDeviceProxy * proxy) override;
53 1 : void StopCommissioning() { mStopCommissioning = true; };
54 :
55 : CHIP_ERROR CommissioningStepFinished(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report) override;
56 :
57 : ByteSpan GetAttestationElements() const { return ByteSpan(mAttestationElements, mAttestationElementsLen); }
58 : ByteSpan GetAttestationSignature() const { return ByteSpan(mAttestationSignature, mAttestationSignatureLen); }
59 : ByteSpan GetAttestationNonce() const { return ByteSpan(mAttestationNonce); }
60 :
61 0 : void SetNetworkSetupNeeded(bool needed) { mNeedsNetworkSetup = needed; }
62 :
63 : protected:
64 : virtual void CleanupCommissioning();
65 : CommissioningStage GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr);
66 : DeviceCommissioner * GetCommissioner() { return mCommissioner; }
67 : CHIP_ERROR PerformStep(CommissioningStage nextStage);
68 : CommissioneeDeviceProxy * GetCommissioneeDeviceProxy() { return mCommissioneeDeviceProxy; }
69 : /**
70 : * The device argument to GetCommandTimeout is the device whose session will
71 : * be used for sending the relevant command.
72 : */
73 : Optional<System::Clock::Timeout> GetCommandTimeout(DeviceProxy * device, CommissioningStage stage) const;
74 : CommissioningParameters mParams = CommissioningParameters();
75 :
76 : private:
77 : DeviceProxy * GetDeviceProxyForStep(CommissioningStage nextStage);
78 :
79 : // Adjust the failsafe timer if CommissioningDelegate GetCASEFailsafeTimerSeconds is set
80 : void SetCASEFailsafeTimerIfNeeded();
81 :
82 : const ByteSpan GetDAC() { return mDAC.Span(); }
83 : const ByteSpan GetPAI() { return mPAI.Span(); }
84 :
85 : CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, Crypto::IdentityProtectionKeySpan ipk,
86 : NodeId adminSubject);
87 : EndpointId GetEndpoint(const CommissioningStage & stage) const;
88 : CommissioningStage GetNextCommissioningStageInternal(CommissioningStage currentStage, CHIP_ERROR & lastErr);
89 :
90 : CHIP_ERROR VerifyICDRegistrationInfo(const CommissioningParameters & params);
91 :
92 : // Helper function to determine whether next stage should be kWiFiNetworkSetup,
93 : // kThreadNetworkSetup, kRequestWiFiCredentials, kRequestThreadCredentials, or
94 : // kCleanup, depending on whether network information has been provided that matches
95 : // the thread/wifi endpoint of the target.
96 : CommissioningStage GetNextCommissioningStageNetworkSetup(CommissioningStage currentStage, CHIP_ERROR & lastErr);
97 :
98 : // Helper function to determine if a scan attempt should be made given the
99 : // scan attempt commissioning params and the corresponding network endpoint of
100 : // the target.
101 4 : bool IsScanNeeded()
102 : {
103 4 : return ((mParams.GetAttemptWiFiNetworkScan().ValueOr(false) &&
104 6 : mDeviceCommissioningInfo.network.wifi.endpoint != kInvalidEndpointId) ||
105 2 : (mParams.GetAttemptThreadNetworkScan().ValueOr(false) &&
106 5 : mDeviceCommissioningInfo.network.thread.endpoint != kInvalidEndpointId));
107 : };
108 :
109 : // Helper function to determine whether secondary network interface is supported.
110 : // Only true if the target has endpoints for both Wi-Fi and Thread, we can
111 : // still talk to it after the first attempt to put it on the network, and
112 : // either we have credentials for both network types or we have credentials
113 : // for either network type (in which case we will prompt for the credentials).
114 6 : bool IsSecondaryNetworkSupported() const
115 : {
116 6 : return ((mParams.GetSupportsConcurrentConnection().ValueOr(false) &&
117 5 : mDeviceCommissioningInfo.network.wifi.endpoint != kInvalidEndpointId &&
118 14 : mDeviceCommissioningInfo.network.thread.endpoint != kInvalidEndpointId) &&
119 9 : mParams.GetWiFiCredentials().HasValue() == mParams.GetThreadOperationalDataset().HasValue());
120 : }
121 :
122 0 : bool IsSomeNetworkSupported() const
123 : {
124 0 : return mDeviceCommissioningInfo.network.wifi.endpoint != kInvalidEndpointId ||
125 0 : mDeviceCommissioningInfo.network.thread.endpoint != kInvalidEndpointId;
126 : }
127 :
128 : // TryingPrimaryNetwork() and TryingSecondaryNetwork() will only be true if
129 : // we decided that a secondary network is supported by our combination of
130 : // commissioner and commissionee.
131 : enum class NetworkAttemptType : uint8_t
132 : {
133 : // We will only try one network type.
134 : kSingle,
135 : // We will try two network types and we are trying the primary right now.
136 : kPrimary,
137 : // We tried the primary and if failed and we are trying the secondary
138 : // now.
139 : kSecondary,
140 : };
141 :
142 0 : void TryPrimaryNetwork() { mTryingNetworkType = NetworkAttemptType::kPrimary; }
143 0 : bool TryingPrimaryNetwork() const { return mTryingNetworkType == NetworkAttemptType::kPrimary; }
144 1 : void TrySecondaryNetwork() { mTryingNetworkType = NetworkAttemptType::kSecondary; }
145 2 : bool TryingSecondaryNetwork() const { return mTryingNetworkType == NetworkAttemptType::kSecondary; }
146 1 : void ResetNetworkAttemptType() { mTryingNetworkType = NetworkAttemptType::kSingle; }
147 :
148 : NetworkAttemptType mTryingNetworkType = NetworkAttemptType::kSingle;
149 :
150 : bool mStopCommissioning = false;
151 :
152 : DeviceCommissioner * mCommissioner = nullptr;
153 : CommissioneeDeviceProxy * mCommissioneeDeviceProxy = nullptr;
154 : OperationalCredentialsDelegate * mOperationalCredentialsDelegate = nullptr;
155 : OperationalDeviceProxy mOperationalDeviceProxy;
156 :
157 : // BEGIN memory space for commissioning parameters that are Spans or similar pointers:
158 : // The caller is not guaranteed to retain the memory these parameters point to.
159 : uint8_t mSsid[CommissioningParameters::kMaxSsidLen];
160 : uint8_t mCredentials[CommissioningParameters::kMaxCredentialsLen];
161 : uint8_t mThreadOperationalDataset[CommissioningParameters::kMaxThreadDatasetLen];
162 : char mCountryCode[CommissioningParameters::kMaxCountryCodeLen];
163 :
164 : // Time zone is statically allocated because it is max 2 and not trivially destructible
165 : static constexpr size_t kMaxSupportedTimeZones = 2;
166 : app::Clusters::TimeSynchronization::Structs::TimeZoneStruct::Type mTimeZoneBuf[kMaxSupportedTimeZones];
167 : static constexpr size_t kMaxTimeZoneNameLen = 64;
168 : char mTimeZoneNames[kMaxTimeZoneNameLen][kMaxSupportedTimeZones];
169 :
170 : // DSTOffsetStructs are similarly not trivially destructible. They don't have a defined size, but we're
171 : // going to do static allocation of the buffers anyway until we replace chip::Optional with std::optional.
172 : static constexpr size_t kMaxSupportedDstStructs = 10;
173 : app::Clusters::TimeSynchronization::Structs::DSTOffsetStruct::Type mDstOffsetsBuf[kMaxSupportedDstStructs];
174 :
175 : static constexpr size_t kMaxDefaultNtpSize = 128;
176 :
177 : char mDefaultNtp[kMaxDefaultNtpSize];
178 :
179 : uint8_t mICDSymmetricKey[Crypto::kAES_CCM128_Key_Length];
180 : Platform::ScopedMemoryBufferWithSize<app::AttributePathParams> mExtraReadPaths;
181 :
182 : // END memory space for commisisoning parameters
183 :
184 : bool mNeedsNetworkSetup = false;
185 : ReadCommissioningInfo mDeviceCommissioningInfo;
186 : bool mNeedsDST = false;
187 :
188 : bool mNeedIcdRegistration = false;
189 : // TODO: Why were the nonces statically allocated, but the certs dynamically allocated?
190 : Platform::ScopedMemoryBufferWithSize<uint8_t> mDAC;
191 : Platform::ScopedMemoryBufferWithSize<uint8_t> mPAI;
192 :
193 : uint8_t mAttestationNonce[kAttestationNonceLength];
194 : uint8_t mCSRNonce[kCSRNonceLength];
195 : uint8_t mNOCertBuffer[Credentials::kMaxCHIPCertLength];
196 : uint8_t mICACertBuffer[Credentials::kMaxCHIPCertLength];
197 :
198 : uint16_t mAttestationElementsLen = 0;
199 : uint8_t mAttestationElements[Credentials::kMaxRspLen];
200 : uint16_t mAttestationSignatureLen = 0;
201 : uint8_t mAttestationSignature[Crypto::kMax_ECDSA_Signature_Length];
202 : };
203 : } // namespace Controller
204 : } // namespace chip
|