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 :
19 : #pragma once
20 : #include <app-common/zap-generated/cluster-objects.h>
21 : #include <app/OperationalSessionSetup.h>
22 : #include <controller/CommissioneeDeviceProxy.h>
23 : #include <credentials/attestation_verifier/DeviceAttestationDelegate.h>
24 : #include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
25 : #include <lib/support/Variant.h>
26 : #include <system/SystemClock.h>
27 :
28 : namespace chip {
29 : namespace Controller {
30 :
31 : class DeviceCommissioner;
32 :
33 : enum CommissioningStage : uint8_t
34 : {
35 : kError,
36 : kSecurePairing, ///< Establish a PASE session with the device
37 : kReadCommissioningInfo, ///< Query General Commissioning Attributes, Network Features and Time Synchronization Cluster
38 : kReadCommissioningInfo2, ///< Query SupportsConcurrentConnection, ICD state, check for matching fabric
39 : kArmFailsafe, ///< Send ArmFailSafe (0x30:0) command to the device
40 : kConfigRegulatory, ///< Send SetRegulatoryConfig (0x30:2) command to the device
41 : kConfigureUTCTime, ///< SetUTCTime if the DUT has a time cluster
42 : kConfigureTimeZone, ///< Configure a time zone if one is required and available
43 : kConfigureDSTOffset, ///< Configure DST offset if one is required and available
44 : kConfigureDefaultNTP, ///< Configure a default NTP server if one is required and available
45 : kSendPAICertificateRequest, ///< Send PAI CertificateChainRequest (0x3E:2) command to the device
46 : kSendDACCertificateRequest, ///< Send DAC CertificateChainRequest (0x3E:2) command to the device
47 : kSendAttestationRequest, ///< Send AttestationRequest (0x3E:0) command to the device
48 : kAttestationVerification, ///< Verify AttestationResponse (0x3E:1) validity
49 : kSendOpCertSigningRequest, ///< Send CSRRequest (0x3E:4) command to the device
50 : kValidateCSR, ///< Verify CSRResponse (0x3E:5) validity
51 : kGenerateNOCChain, ///< TLV encode Node Operational Credentials (NOC) chain certs
52 : kSendTrustedRootCert, ///< Send AddTrustedRootCertificate (0x3E:11) command to the device
53 : kSendNOC, ///< Send AddNOC (0x3E:6) command to the device
54 : kConfigureTrustedTimeSource, ///< Configure a trusted time source if one is required and available (must be done after SendNOC)
55 : kICDGetRegistrationInfo, ///< Waiting for the higher layer to provide ICD registraion informations.
56 : kICDRegistration, ///< Register for ICD management
57 : kICDSendStayActive, ///< Send Keep Alive to ICD
58 : kWiFiNetworkSetup, ///< Send AddOrUpdateWiFiNetwork (0x31:2) command to the device
59 : kThreadNetworkSetup, ///< Send AddOrUpdateThreadNetwork (0x31:3) command to the device
60 : kFailsafeBeforeWiFiEnable, ///< Extend the fail-safe before doing kWiFiNetworkEnable
61 : kFailsafeBeforeThreadEnable, ///< Extend the fail-safe before doing kThreadNetworkEnable
62 : kWiFiNetworkEnable, ///< Send ConnectNetwork (0x31:6) command to the device for the WiFi network
63 : kThreadNetworkEnable, ///< Send ConnectNetwork (0x31:6) command to the device for the Thread network
64 : kFindOperational, ///< Perform operational discovery and establish a CASE session with the device
65 : kSendComplete, ///< Send CommissioningComplete (0x30:4) command to the device
66 : kCleanup, ///< Call delegates with status, free memory, clear timers and state
67 : /// Send ScanNetworks (0x31:0) command to the device.
68 : /// ScanNetworks can happen anytime after kArmFailsafe.
69 : /// However, the cirque tests fail if it is earlier in the list
70 : kScanNetworks,
71 : /// Waiting for the higher layer to provide network credentials before continuing the workflow.
72 : /// Call CHIPDeviceController::NetworkCredentialsReady() when CommissioningParameters is populated with
73 : /// network credentials to use in kWiFiNetworkSetup or kThreadNetworkSetup steps.
74 : kNeedsNetworkCreds,
75 : };
76 :
77 : enum ICDRegistrationStrategy : uint8_t
78 : {
79 : kIgnore, ///< Do not check whether the device is an ICD during commissioning
80 : kBeforeComplete, ///< Do commissioner self-registration or external controller registration,
81 : ///< Controller should provide a ICDKey manager for generating symmetric key
82 : };
83 :
84 : const char * StageToString(CommissioningStage stage);
85 :
86 : struct WiFiCredentials
87 : {
88 : ByteSpan ssid;
89 : ByteSpan credentials;
90 0 : WiFiCredentials(ByteSpan newSsid, ByteSpan newCreds) : ssid(newSsid), credentials(newCreds) {}
91 : };
92 :
93 : struct NOCChainGenerationParameters
94 : {
95 : ByteSpan nocsrElements;
96 : ByteSpan signature;
97 : };
98 :
99 : struct CompletionStatus
100 : {
101 0 : CompletionStatus() : err(CHIP_NO_ERROR), failedStage(NullOptional), attestationResult(NullOptional) {}
102 : CHIP_ERROR err;
103 : Optional<CommissioningStage> failedStage;
104 : Optional<Credentials::AttestationVerificationResult> attestationResult;
105 : Optional<app::Clusters::GeneralCommissioning::CommissioningErrorEnum> commissioningError;
106 : Optional<app::Clusters::NetworkCommissioning::NetworkCommissioningStatusEnum> networkCommissioningStatus;
107 : };
108 :
109 : inline constexpr uint16_t kDefaultFailsafeTimeout = 60;
110 :
111 : // Per spec, all commands that are sent with the failsafe armed need at least
112 : // a 30s timeout.
113 : inline constexpr System::Clock::Timeout kMinimumCommissioningStepTimeout = System::Clock::Seconds16(30);
114 :
115 : class CommissioningParameters
116 : {
117 : public:
118 : static constexpr size_t kMaxThreadDatasetLen = 254;
119 : static constexpr size_t kMaxSsidLen = 32;
120 : static constexpr size_t kMaxCredentialsLen = 64;
121 : static constexpr size_t kMaxCountryCodeLen = 2;
122 :
123 : // Value to use when setting the commissioning failsafe timer on the node being commissioned.
124 : // If the failsafe timer value is passed in as part of the commissioning parameters, that value will be used. If not supplied,
125 : // the AutoCommissioner will set this to the recommended value read from the node. If that is not set, it will fall back to the
126 : // default kDefaultFailsafeTimeout.
127 : // This value should be set before running PerformCommissioningStep for the kArmFailsafe step.
128 0 : const Optional<uint16_t> GetFailsafeTimerSeconds() const { return mFailsafeTimerSeconds; }
129 :
130 : // Value to use when re-setting the commissioning failsafe timer immediately prior to operational discovery.
131 : // If a CASE failsafe timer value is passed in as part of the commissioning parameters, then the failsafe timer
132 : // will be reset using this value before operational discovery begins. If not supplied, then the AutoCommissioner
133 : // will not automatically reset the failsafe timer before operational discovery begins. It can be useful for the
134 : // commissioner to set the CASE failsafe timer to a small value (ex. 30s) when the regular failsafe timer is set
135 : // to a larger value to accommodate user interaction during setup (network credential selection, user consent
136 : // after device attestation).
137 0 : const Optional<uint16_t> GetCASEFailsafeTimerSeconds() const { return mCASEFailsafeTimerSeconds; }
138 :
139 : // The location (indoor/outdoor) of the node being commissioned.
140 : // The node regulartory location (indoor/outdoor) should be set by the commissioner explicitly as it may be different than the
141 : // location of the commissioner. This location will be set on the node if the node supports configurable regulatory location
142 : // (from GetLocationCapability - see below). If the regulatory location is not supplied, this will fall back to the location in
143 : // GetDefaultRegulatoryLocation and then to Outdoor (most restrictive).
144 : // This value should be set before calling PerformCommissioningStep for the kConfigRegulatory step.
145 0 : const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> GetDeviceRegulatoryLocation() const
146 : {
147 0 : return mDeviceRegulatoryLocation;
148 : }
149 :
150 : // Value to determine whether the node supports Concurrent Connections as read from the GeneralCommissioning cluster.
151 : // In the AutoCommissioner, this is automatically set from from the kReadCommissioningInfo2 stage.
152 0 : Optional<bool> GetSupportsConcurrentConnection() const { return mSupportsConcurrentConnection; }
153 :
154 : // The country code to be used for the node, if set.
155 0 : Optional<CharSpan> GetCountryCode() const { return mCountryCode; }
156 :
157 : // Time zone to set for the node
158 : // If required, this will be truncated to fit the max size allowable on the node
159 0 : Optional<app::DataModel::List<app::Clusters::TimeSynchronization::Structs::TimeZoneStruct::Type>> GetTimeZone() const
160 : {
161 0 : return mTimeZone;
162 : }
163 :
164 : // DST offset list. If required, this will be truncated to fit the max size allowable on the node
165 : // DST list will only be sent if the commissionee requires DST offsets, as indicated in the SetTimeZone response
166 0 : Optional<app::DataModel::List<app::Clusters::TimeSynchronization::Structs::DSTOffsetStruct::Type>> GetDSTOffsets() const
167 : {
168 0 : return mDSTOffsets;
169 : }
170 :
171 : // Default NTP to set on the node if supported and required
172 : // Default implementation will not overide a value already set on the commissionee
173 : // TODO: Add a force option?
174 0 : Optional<app::DataModel::Nullable<CharSpan>> GetDefaultNTP() const { return mDefaultNTP; }
175 :
176 : // Trusted time source
177 : // Default implementation will not override a value already set on the commissionee
178 : // TODO: Add a force option?
179 : Optional<app::DataModel::Nullable<app::Clusters::TimeSynchronization::Structs::FabricScopedTrustedTimeSourceStruct::Type>>
180 0 : GetTrustedTimeSource() const
181 : {
182 0 : return mTrustedTimeSource;
183 : }
184 :
185 : // Nonce sent to the node to use during the CSR request.
186 : // When using the AutoCommissioner, this value will be ignored in favour of the value supplied by the
187 : // OperationalCredentialsDelegate ObtainCsrNonce function. If the credential delegate is not supplied, the value supplied here
188 : // will be used. If neither is supplied random value will be used as a fallback.
189 : // This value must be set before calling PerformCommissioningStep for the kSendOpCertSigningRequest step.
190 0 : const Optional<ByteSpan> GetCSRNonce() const { return mCSRNonce; }
191 :
192 : // Nonce value sent to the node to use during the attestation request.
193 : // When using the AutoCommissioner, this value will fall back to random if not supplied.
194 : // If a non-random value is to be used, the value must be set before calling PerformCommissioningStep for the
195 : // kSendAttestationRequest step.
196 0 : const Optional<ByteSpan> GetAttestationNonce() const { return mAttestationNonce; }
197 :
198 : // WiFi SSID and credentials to use when adding/updating and enabling WiFi on the node.
199 : // This value must be set before calling PerformCommissioningStep for the kWiFiNetworkSetup or kWiFiNetworkEnable steps.
200 0 : const Optional<WiFiCredentials> GetWiFiCredentials() const { return mWiFiCreds; }
201 :
202 : // Thread operational dataset to use when adding/updating and enabling the thread network on the node.
203 : // This value must be set before calling PerformCommissioningStep for the kThreadNetworkSetup or kThreadNetworkEnable steps.
204 0 : const Optional<ByteSpan> GetThreadOperationalDataset() const { return mThreadOperationalDataset; }
205 :
206 : // The NOCSR parameters (elements and signature) returned from the node. In the AutoCommissioner, this is set using the data
207 : // returned from the kSendOpCertSigningRequest stage.
208 : // This value must be set before calling PerformCommissioningStep for the kGenerateNOCChain step.
209 0 : const Optional<NOCChainGenerationParameters> GetNOCChainGenerationParameters() const { return mNOCChainGenerationParameters; }
210 :
211 : // The root certificate for the operational certificate chain. In the auto commissioner, this is set by by the kGenerateNOCChain
212 : // stage through the OperationalCredentialsDelegate.
213 : // This value must be set before calling PerformCommissioningStep for the kSendTrustedRootCert step.
214 0 : const Optional<ByteSpan> GetRootCert() const { return mRootCert; }
215 :
216 : // The node operational certificate for the node being commissioned. In the AutoCommissioner, this is set by by the
217 : // kGenerateNOCChain stage through the OperationalCredentialsDelegate.
218 : // This value must be set before calling PerformCommissioningStep for the kSendNOC step.
219 : // This value must also be set before calling PerformCommissioningStep for the kSendTrustedRootCert step, as it is used to set
220 : // the node id in the DeviceProxy.
221 0 : const Optional<ByteSpan> GetNoc() const { return mNoc; }
222 :
223 : // The intermediate certificate for the node being commissioned. In the AutoCommissioner, this is set by by the
224 : // kGenerateNOCChain stage through the OperationalCredentialsDelegate.
225 : // This value should be set before calling PerformCommissioningStep for the kSendNOC step.
226 0 : const Optional<ByteSpan> GetIcac() const { return mIcac; }
227 :
228 : // Epoch key for the identity protection key for the node being commissioned. In the AutoCommissioner, this is set by by the
229 : // kGenerateNOCChain stage through the OperationalCredentialsDelegate.
230 : // This value must be set before calling PerformCommissioningStep for the kSendNOC step.
231 0 : const Optional<IdentityProtectionKeySpan> GetIpk() const
232 : {
233 0 : return mIpk.HasValue() ? Optional<IdentityProtectionKeySpan>(mIpk.Value().Span()) : Optional<IdentityProtectionKeySpan>();
234 : }
235 :
236 : // Admin subject id used for the case access control entry created if the AddNOC command succeeds. In the AutoCommissioner, this
237 : // is set by by the kGenerateNOCChain stage through the OperationalCredentialsDelegate.
238 : // This must be set before calling PerformCommissioningStep for the kSendNOC step.
239 0 : const Optional<NodeId> GetAdminSubject() const { return mAdminSubject; }
240 :
241 : // Attestation elements from the node. These are obtained from node in response to the AttestationRequest command. In the
242 : // AutoCommissioner, this is automatically set from the report from the kSendAttestationRequest stage.
243 : // This must be set before calling PerformCommissioningStep for the kAttestationVerification step.
244 0 : const Optional<ByteSpan> GetAttestationElements() const { return mAttestationElements; }
245 :
246 : // Attestation signature from the node. This is obtained from node in response to the AttestationRequest command. In the
247 : // AutoCommissioner, this is automatically set from the report from the kSendAttestationRequest stage.
248 : // This must be set before calling PerformCommissioningStep for the kAttestationVerification step.
249 0 : const Optional<ByteSpan> GetAttestationSignature() const { return mAttestationSignature; }
250 :
251 : // Product attestation intermediate certificate from the node. This is obtained from the node in response to the
252 : // CertificateChainRequest command for the PAI. In the AutoCommissioner, this is automatically set from the report from the
253 : // kSendPAICertificateRequest stage.
254 : // This must be set before calling PerformCommissioningStep for the kAttestationVerificationstep.
255 0 : const Optional<ByteSpan> GetPAI() const { return mPAI; }
256 :
257 : // Device attestation certificate from the node. This is obtained from the node in response to the CertificateChainRequest
258 : // command for the DAC. In the AutoCommissioner, this is automatically set from the report from the kSendDACCertificateRequest
259 : // stage.
260 : // This must be set before calling PerformCommissioningStep for the kAttestationVerification step.
261 0 : const Optional<ByteSpan> GetDAC() const { return mDAC; }
262 :
263 : // Node ID when a matching fabric is found in the Node Operational Credentials cluster.
264 : // In the AutoCommissioner, this is set from kReadCommissioningInfo stage.
265 : const Optional<NodeId> GetRemoteNodeId() const { return mRemoteNodeId; }
266 :
267 : // Node vendor ID from the basic information cluster. In the AutoCommissioner, this is automatically set from report from the
268 : // kReadCommissioningInfo stage.
269 : // This must be set before calling PerformCommissioningStep for the kAttestationVerification step.
270 0 : const Optional<VendorId> GetRemoteVendorId() const { return mRemoteVendorId; }
271 :
272 : // Node product ID from the basic information cluster. In the AutoCommissioner, this is automatically set from report from the
273 : // kReadCommissioningInfo stage.
274 : // This must be set before calling PerformCommissioningStep for the kAttestationVerification step.
275 0 : const Optional<uint16_t> GetRemoteProductId() const { return mRemoteProductId; }
276 :
277 : // Default regulatory location set by the node, as read from the GeneralCommissioning cluster. In the AutoCommissioner, this is
278 : // automatically set from report from the kReadCommissioningInfo stage.
279 : // This should be set before calling PerformCommissioningStep for the kConfigRegulatory step.
280 0 : const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> GetDefaultRegulatoryLocation() const
281 : {
282 0 : return mDefaultRegulatoryLocation;
283 : }
284 :
285 : // Location capabilities of the node, as read from the GeneralCommissioning cluster. In the AutoCommissioner, this is
286 : // automatically set from report from the kReadCommissioningInfo stage.
287 : // This should be set before calling PerformCommissioningStep for the kConfigRegulatory step.
288 0 : const Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> GetLocationCapability() const
289 : {
290 0 : return mLocationCapability;
291 : }
292 :
293 : // Status to send when calling CommissioningComplete on the PairingDelegate during the kCleanup step. The AutoCommissioner uses
294 : // this to pass through any error messages received during commissioning.
295 0 : const CompletionStatus & GetCompletionStatus() const { return completionStatus; }
296 :
297 0 : CommissioningParameters & SetFailsafeTimerSeconds(uint16_t seconds)
298 : {
299 0 : mFailsafeTimerSeconds.SetValue(seconds);
300 0 : return *this;
301 : }
302 :
303 : CommissioningParameters & SetCASEFailsafeTimerSeconds(uint16_t seconds)
304 : {
305 : mCASEFailsafeTimerSeconds.SetValue(seconds);
306 : return *this;
307 : }
308 :
309 : CommissioningParameters & SetDeviceRegulatoryLocation(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum location)
310 : {
311 : mDeviceRegulatoryLocation.SetValue(location);
312 : return *this;
313 : }
314 :
315 0 : CommissioningParameters & SetSupportsConcurrentConnection(bool concurrentConnection)
316 : {
317 0 : mSupportsConcurrentConnection.SetValue(concurrentConnection);
318 0 : return *this;
319 : }
320 :
321 : // The lifetime of the buffer countryCode is pointing to should exceed the
322 : // lifetime of CommissioningParameters object.
323 0 : CommissioningParameters & SetCountryCode(CharSpan countryCode)
324 : {
325 0 : mCountryCode.SetValue(countryCode);
326 0 : return *this;
327 : }
328 :
329 : // The lifetime of the list buffer needs to exceed the lifetime of the CommissioningParameters object.
330 : CommissioningParameters &
331 0 : SetTimeZone(app::DataModel::List<app::Clusters::TimeSynchronization::Structs::TimeZoneStruct::Type> timeZone)
332 : {
333 0 : mTimeZone.SetValue(timeZone);
334 0 : return *this;
335 : }
336 :
337 : // The lifetime of the list buffer needs to exceed the lifetime of the CommissioningParameters object.
338 : CommissioningParameters &
339 0 : SetDSTOffsets(app::DataModel::List<app::Clusters::TimeSynchronization::Structs::DSTOffsetStruct::Type> dstOffsets)
340 : {
341 0 : mDSTOffsets.SetValue(dstOffsets);
342 0 : return *this;
343 : }
344 :
345 : // The lifetime of the char span needs to exceed the lifetime of the CommissioningParameters
346 0 : CommissioningParameters & SetDefaultNTP(app::DataModel::Nullable<CharSpan> defaultNTP)
347 : {
348 0 : mDefaultNTP.SetValue(defaultNTP);
349 0 : return *this;
350 : }
351 :
352 : CommissioningParameters & SetTrustedTimeSource(
353 : app::DataModel::Nullable<app::Clusters::TimeSynchronization::Structs::FabricScopedTrustedTimeSourceStruct::Type>
354 : trustedTimeSource)
355 : {
356 : mTrustedTimeSource.SetValue(trustedTimeSource);
357 : return *this;
358 : }
359 :
360 : // The lifetime of the buffer csrNonce is pointing to, should exceed the lifetime of CommissioningParameters object.
361 0 : CommissioningParameters & SetCSRNonce(ByteSpan csrNonce)
362 : {
363 0 : mCSRNonce.SetValue(csrNonce);
364 0 : return *this;
365 : }
366 :
367 : // The lifetime of the buffer attestationNonce is pointing to, should exceed the lifetime of CommissioningParameters object.
368 0 : CommissioningParameters & SetAttestationNonce(ByteSpan attestationNonce)
369 : {
370 0 : mAttestationNonce.SetValue(attestationNonce);
371 0 : return *this;
372 : }
373 0 : CommissioningParameters & SetWiFiCredentials(WiFiCredentials wifiCreds)
374 : {
375 0 : mWiFiCreds.SetValue(wifiCreds);
376 0 : return *this;
377 : }
378 :
379 : // If a ThreadOperationalDataset is provided, then the ThreadNetworkScan will not be attempted
380 0 : CommissioningParameters & SetThreadOperationalDataset(ByteSpan threadOperationalDataset)
381 : {
382 :
383 0 : mThreadOperationalDataset.SetValue(threadOperationalDataset);
384 0 : mAttemptThreadNetworkScan = MakeOptional(static_cast<bool>(false));
385 0 : return *this;
386 : }
387 : // This parameter should be set with the information returned from kSendOpCertSigningRequest. It must be set before calling
388 : // kGenerateNOCChain.
389 0 : CommissioningParameters & SetNOCChainGenerationParameters(const NOCChainGenerationParameters & params)
390 : {
391 0 : mNOCChainGenerationParameters.SetValue(params);
392 0 : return *this;
393 : }
394 : // Root certs can be generated from the kGenerateNOCChain step. This must be set before calling kSendTrustedRootCert.
395 0 : CommissioningParameters & SetRootCert(const ByteSpan & rcac)
396 : {
397 0 : mRootCert.SetValue(rcac);
398 0 : return *this;
399 : }
400 : // NOC and intermediate cert can be generated from the kGenerateNOCChain step. NOC must be set before calling
401 : // kSendTrustedRootCert. ICAC and NOC must be set before calling kSendNOC
402 0 : CommissioningParameters & SetNoc(const ByteSpan & noc)
403 : {
404 0 : mNoc.SetValue(noc);
405 0 : return *this;
406 : }
407 0 : CommissioningParameters & SetIcac(const ByteSpan & icac)
408 : {
409 0 : mIcac.SetValue(icac);
410 0 : return *this;
411 : }
412 0 : CommissioningParameters & SetIpk(const IdentityProtectionKeySpan ipk)
413 : {
414 0 : mIpk.SetValue(IdentityProtectionKey(ipk));
415 0 : return *this;
416 : }
417 0 : CommissioningParameters & SetAdminSubject(const NodeId adminSubject)
418 : {
419 0 : mAdminSubject.SetValue(adminSubject);
420 0 : return *this;
421 : }
422 0 : CommissioningParameters & SetAttestationElements(const ByteSpan & attestationElements)
423 : {
424 0 : mAttestationElements = MakeOptional(attestationElements);
425 0 : return *this;
426 : }
427 0 : CommissioningParameters & SetAttestationSignature(const ByteSpan & attestationSignature)
428 : {
429 0 : mAttestationSignature = MakeOptional(attestationSignature);
430 0 : return *this;
431 : }
432 0 : CommissioningParameters & SetPAI(const ByteSpan & pai)
433 : {
434 0 : mPAI = MakeOptional(pai);
435 0 : return *this;
436 : }
437 0 : CommissioningParameters & SetDAC(const ByteSpan & dac)
438 : {
439 0 : mDAC = MakeOptional(dac);
440 0 : return *this;
441 : }
442 0 : CommissioningParameters & SetRemoteNodeId(NodeId id)
443 : {
444 0 : mRemoteNodeId = MakeOptional(id);
445 0 : return *this;
446 : }
447 0 : CommissioningParameters & SetRemoteVendorId(VendorId id)
448 : {
449 0 : mRemoteVendorId = MakeOptional(id);
450 0 : return *this;
451 : }
452 0 : CommissioningParameters & SetRemoteProductId(uint16_t id)
453 : {
454 0 : mRemoteProductId = MakeOptional(id);
455 0 : return *this;
456 : }
457 0 : CommissioningParameters & SetDefaultRegulatoryLocation(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum location)
458 : {
459 0 : mDefaultRegulatoryLocation = MakeOptional(location);
460 0 : return *this;
461 : }
462 0 : CommissioningParameters & SetLocationCapability(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum capability)
463 : {
464 0 : mLocationCapability = MakeOptional(capability);
465 0 : return *this;
466 : }
467 0 : void SetCompletionStatus(const CompletionStatus & status) { completionStatus = status; }
468 :
469 : CommissioningParameters & SetDeviceAttestationDelegate(Credentials::DeviceAttestationDelegate * deviceAttestationDelegate)
470 : {
471 : mDeviceAttestationDelegate = deviceAttestationDelegate;
472 : return *this;
473 : }
474 :
475 0 : Credentials::DeviceAttestationDelegate * GetDeviceAttestationDelegate() const { return mDeviceAttestationDelegate; }
476 :
477 : // If an SSID is provided, and AttemptWiFiNetworkScan is true,
478 : // then a directed scan will be performed using the SSID provided in the WiFiCredentials object
479 0 : Optional<bool> GetAttemptWiFiNetworkScan() const { return mAttemptWiFiNetworkScan; }
480 : CommissioningParameters & SetAttemptWiFiNetworkScan(bool attemptWiFiNetworkScan)
481 : {
482 : mAttemptWiFiNetworkScan = MakeOptional(attemptWiFiNetworkScan);
483 : return *this;
484 : }
485 :
486 : // If a ThreadOperationalDataset is provided, then the ThreadNetworkScan will not be attempted
487 0 : Optional<bool> GetAttemptThreadNetworkScan() const { return mAttemptThreadNetworkScan; }
488 : CommissioningParameters & SetAttemptThreadNetworkScan(bool attemptThreadNetworkScan)
489 : {
490 : if (!mThreadOperationalDataset.HasValue())
491 : {
492 : mAttemptThreadNetworkScan = MakeOptional(attemptThreadNetworkScan);
493 : }
494 : return *this;
495 : }
496 :
497 : // Only perform the PASE steps of commissioning.
498 : // Commissioning will be completed by another admin on the network.
499 0 : Optional<bool> GetSkipCommissioningComplete() const { return mSkipCommissioningComplete; }
500 : CommissioningParameters & SetSkipCommissioningComplete(bool skipCommissioningComplete)
501 : {
502 : mSkipCommissioningComplete = MakeOptional(skipCommissioningComplete);
503 : return *this;
504 : }
505 :
506 : // Check for matching fabric on target device by reading fabric list and looking for a
507 : // fabricId and RootCert match. If a match is detected, then use GetNodeId() to
508 : // access the nodeId for the device on the matching fabric.
509 0 : bool GetCheckForMatchingFabric() const { return mCheckForMatchingFabric; }
510 : CommissioningParameters & SetCheckForMatchingFabric(bool checkForMatchingFabric)
511 : {
512 : mCheckForMatchingFabric = checkForMatchingFabric;
513 : return *this;
514 : }
515 :
516 0 : ICDRegistrationStrategy GetICDRegistrationStrategy() const { return mICDRegistrationStrategy; }
517 : CommissioningParameters & SetICDRegistrationStrategy(ICDRegistrationStrategy icdRegistrationStrategy)
518 : {
519 : mICDRegistrationStrategy = icdRegistrationStrategy;
520 : return *this;
521 : }
522 :
523 0 : Optional<NodeId> GetICDCheckInNodeId() const { return mICDCheckInNodeId; }
524 0 : CommissioningParameters & SetICDCheckInNodeId(NodeId icdCheckInNodeId)
525 : {
526 0 : mICDCheckInNodeId = MakeOptional(icdCheckInNodeId);
527 0 : return *this;
528 : }
529 :
530 0 : Optional<uint64_t> GetICDMonitoredSubject() const { return mICDMonitoredSubject; }
531 0 : CommissioningParameters & SetICDMonitoredSubject(uint64_t icdMonitoredSubject)
532 : {
533 0 : mICDMonitoredSubject = MakeOptional(icdMonitoredSubject);
534 0 : return *this;
535 : }
536 :
537 0 : Optional<ByteSpan> GetICDSymmetricKey() const { return mICDSymmetricKey; }
538 0 : CommissioningParameters & SetICDSymmetricKey(ByteSpan icdSymmetricKey)
539 : {
540 0 : mICDSymmetricKey = MakeOptional(icdSymmetricKey);
541 0 : return *this;
542 : }
543 :
544 : // Clear all members that depend on some sort of external buffer. Can be
545 : // used to make sure that we are not holding any dangling pointers.
546 0 : void ClearExternalBufferDependentValues()
547 : {
548 0 : mCSRNonce.ClearValue();
549 0 : mAttestationNonce.ClearValue();
550 0 : mWiFiCreds.ClearValue();
551 0 : mCountryCode.ClearValue();
552 0 : mThreadOperationalDataset.ClearValue();
553 0 : mNOCChainGenerationParameters.ClearValue();
554 0 : mRootCert.ClearValue();
555 0 : mNoc.ClearValue();
556 0 : mIcac.ClearValue();
557 0 : mIpk.ClearValue();
558 0 : mAttestationElements.ClearValue();
559 0 : mAttestationSignature.ClearValue();
560 0 : mPAI.ClearValue();
561 0 : mDAC.ClearValue();
562 0 : mTimeZone.ClearValue();
563 0 : mDSTOffsets.ClearValue();
564 0 : mDefaultNTP.ClearValue();
565 0 : mICDSymmetricKey.ClearValue();
566 0 : }
567 :
568 : private:
569 : // Items that can be set by the commissioner
570 : Optional<uint16_t> mFailsafeTimerSeconds;
571 : Optional<uint16_t> mCASEFailsafeTimerSeconds;
572 : Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> mDeviceRegulatoryLocation;
573 : Optional<app::DataModel::List<app::Clusters::TimeSynchronization::Structs::TimeZoneStruct::Type>> mTimeZone;
574 : Optional<app::DataModel::List<app::Clusters::TimeSynchronization::Structs::DSTOffsetStruct::Type>> mDSTOffsets;
575 : Optional<app::DataModel::Nullable<CharSpan>> mDefaultNTP;
576 : Optional<app::DataModel::Nullable<app::Clusters::TimeSynchronization::Structs::FabricScopedTrustedTimeSourceStruct::Type>>
577 : mTrustedTimeSource;
578 : Optional<ByteSpan> mCSRNonce;
579 : Optional<ByteSpan> mAttestationNonce;
580 : Optional<WiFiCredentials> mWiFiCreds;
581 : Optional<CharSpan> mCountryCode;
582 : Optional<ByteSpan> mThreadOperationalDataset;
583 : Optional<NOCChainGenerationParameters> mNOCChainGenerationParameters;
584 : Optional<ByteSpan> mRootCert;
585 : Optional<ByteSpan> mNoc;
586 : Optional<ByteSpan> mIcac;
587 : Optional<IdentityProtectionKey> mIpk;
588 : Optional<NodeId> mAdminSubject;
589 : // Items that come from the device in commissioning steps
590 : Optional<ByteSpan> mAttestationElements;
591 : Optional<ByteSpan> mAttestationSignature;
592 : Optional<ByteSpan> mPAI;
593 : Optional<ByteSpan> mDAC;
594 : Optional<NodeId> mRemoteNodeId;
595 : Optional<VendorId> mRemoteVendorId;
596 : Optional<uint16_t> mRemoteProductId;
597 : Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> mDefaultRegulatoryLocation;
598 : Optional<app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum> mLocationCapability;
599 : Optional<bool> mSupportsConcurrentConnection;
600 : CompletionStatus completionStatus;
601 : Credentials::DeviceAttestationDelegate * mDeviceAttestationDelegate =
602 : nullptr; // Delegate to handle device attestation failures during commissioning
603 : Optional<bool> mAttemptWiFiNetworkScan;
604 : Optional<bool> mAttemptThreadNetworkScan; // This automatically gets set to false when a ThreadOperationalDataset is set
605 : Optional<bool> mSkipCommissioningComplete;
606 :
607 : Optional<NodeId> mICDCheckInNodeId;
608 : Optional<uint64_t> mICDMonitoredSubject;
609 : Optional<ByteSpan> mICDSymmetricKey;
610 :
611 : ICDRegistrationStrategy mICDRegistrationStrategy = ICDRegistrationStrategy::kIgnore;
612 : bool mCheckForMatchingFabric = false;
613 : };
614 :
615 : struct RequestedCertificate
616 : {
617 0 : RequestedCertificate(ByteSpan newCertificate) : certificate(newCertificate) {}
618 : ByteSpan certificate;
619 : };
620 :
621 : struct AttestationResponse
622 : {
623 0 : AttestationResponse(ByteSpan newAttestationElements, ByteSpan newSignature) :
624 0 : attestationElements(newAttestationElements), signature(newSignature)
625 0 : {}
626 : ByteSpan attestationElements;
627 : ByteSpan signature;
628 : };
629 :
630 : struct CSRResponse
631 : {
632 0 : CSRResponse(ByteSpan elements, ByteSpan newSignature) : nocsrElements(elements), signature(newSignature) {}
633 : ByteSpan nocsrElements;
634 : ByteSpan signature;
635 : };
636 :
637 : struct NocChain
638 : {
639 0 : NocChain(ByteSpan newNoc, ByteSpan newIcac, ByteSpan newRcac, IdentityProtectionKeySpan newIpk, NodeId newAdminSubject) :
640 0 : noc(newNoc), icac(newIcac), rcac(newRcac), ipk(newIpk), adminSubject(newAdminSubject)
641 0 : {}
642 : ByteSpan noc;
643 : ByteSpan icac;
644 : ByteSpan rcac;
645 : IdentityProtectionKeySpan ipk;
646 : NodeId adminSubject;
647 : };
648 :
649 : struct OperationalNodeFoundData
650 : {
651 0 : OperationalNodeFoundData(OperationalDeviceProxy proxy) : operationalProxy(proxy) {}
652 : OperationalDeviceProxy operationalProxy;
653 : };
654 :
655 : struct NetworkClusterInfo
656 : {
657 : EndpointId endpoint = kInvalidEndpointId;
658 : app::Clusters::NetworkCommissioning::Attributes::ConnectMaxTimeSeconds::TypeInfo::DecodableType minConnectionTime;
659 : };
660 : struct NetworkClusters
661 : {
662 : NetworkClusterInfo wifi;
663 : NetworkClusterInfo thread;
664 : NetworkClusterInfo eth;
665 : };
666 : struct BasicClusterInfo
667 : {
668 : VendorId vendorId = VendorId::Common;
669 : uint16_t productId = 0;
670 : };
671 : struct GeneralCommissioningInfo
672 : {
673 : uint64_t breadcrumb = 0;
674 : uint16_t recommendedFailsafe = 0;
675 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum currentRegulatoryLocation =
676 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kIndoorOutdoor;
677 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum locationCapability =
678 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kIndoorOutdoor;
679 : ;
680 : };
681 :
682 : // ICDManagementClusterInfo is populated when the controller reads information from
683 : // the ICD Management cluster, and is used to communicate that information.
684 : struct ICDManagementClusterInfo
685 : {
686 : // Whether the ICD is capable of functioning as a LIT device. If false, the ICD can only be a SIT device.
687 : bool isLIT;
688 : // Whether the ICD supports the check-in protocol. LIT devices have to support it, but SIT devices
689 : // might or might not.
690 : bool checkInProtocolSupport;
691 :
692 : // userActiveModeTriggerHint indicates which user action(s) will trigger the ICD to switch to Active mode.
693 : // For a LIT: The device is required to provide a value for the bitmap.
694 : // For a SIT: The device may not provide a value. In that case, none of the bits will be set.
695 : //
696 : // userActiveModeTriggerInstruction may provide additional information for users for some specific
697 : // userActiveModeTriggerHint values.
698 : BitMask<app::Clusters::IcdManagement::UserActiveModeTriggerBitmap> userActiveModeTriggerHint;
699 : CharSpan userActiveModeTriggerInstruction;
700 : };
701 :
702 : struct ReadCommissioningInfo
703 : {
704 : NetworkClusters network;
705 : BasicClusterInfo basic;
706 : GeneralCommissioningInfo general;
707 : bool requiresUTC = false;
708 : bool requiresTimeZone = false;
709 : bool requiresDefaultNTP = false;
710 : bool requiresTrustedTimeSource = false;
711 : uint8_t maxTimeZoneSize = 1;
712 : uint8_t maxDSTSize = 1;
713 : NodeId remoteNodeId = kUndefinedNodeId;
714 : bool supportsConcurrentConnection = true;
715 : ICDManagementClusterInfo icd;
716 : };
717 :
718 : struct TimeZoneResponseInfo
719 : {
720 : bool requiresDSTOffsets;
721 : };
722 :
723 : struct AttestationErrorInfo
724 : {
725 0 : AttestationErrorInfo(Credentials::AttestationVerificationResult result) : attestationResult(result) {}
726 : Credentials::AttestationVerificationResult attestationResult;
727 : };
728 :
729 : struct CommissioningErrorInfo
730 : {
731 0 : CommissioningErrorInfo(app::Clusters::GeneralCommissioning::CommissioningErrorEnum result) : commissioningError(result) {}
732 : app::Clusters::GeneralCommissioning::CommissioningErrorEnum commissioningError;
733 : };
734 :
735 : struct NetworkCommissioningStatusInfo
736 : {
737 0 : NetworkCommissioningStatusInfo(app::Clusters::NetworkCommissioning::NetworkCommissioningStatusEnum result) :
738 0 : networkCommissioningStatus(result)
739 0 : {}
740 : app::Clusters::NetworkCommissioning::NetworkCommissioningStatusEnum networkCommissioningStatus;
741 : };
742 :
743 : class CommissioningDelegate
744 : {
745 : public:
746 0 : virtual ~CommissioningDelegate(){};
747 : /* CommissioningReport is returned after each commissioning step is completed. The reports for each step are:
748 : * kReadCommissioningInfo: Reported together with ReadCommissioningInfo2
749 : * kReadCommissioningInfo2: ReadCommissioningInfo
750 : * kArmFailsafe: CommissioningErrorInfo if there is an error
751 : * kConfigRegulatory: CommissioningErrorInfo if there is an error
752 : * kConfigureUTCTime: None
753 : * kConfigureTimeZone: TimeZoneResponseInfo
754 : * kConfigureDSTOffset: None
755 : * kConfigureDefaultNTP: None
756 : * kSendPAICertificateRequest: RequestedCertificate
757 : * kSendDACCertificateRequest: RequestedCertificate
758 : * kSendAttestationRequest: AttestationResponse
759 : * kAttestationVerification: AttestationErrorInfo if there is an error
760 : * kSendOpCertSigningRequest: CSRResponse
761 : * kGenerateNOCChain: NocChain
762 : * kSendTrustedRootCert: None
763 : * kSendNOC: none
764 : * kConfigureTrustedTimeSource: None
765 : * kWiFiNetworkSetup: NetworkCommissioningStatusInfo if there is an error
766 : * kThreadNetworkSetup: NetworkCommissioningStatusInfo if there is an error
767 : * kWiFiNetworkEnable: NetworkCommissioningStatusInfo if there is an error
768 : * kThreadNetworkEnable: NetworkCommissioningStatusInfo if there is an error
769 : * kFindOperational: OperationalNodeFoundData
770 : * kSendComplete: CommissioningErrorInfo if there is an error
771 : * kCleanup: none
772 : */
773 : struct CommissioningReport
774 : : Variant<RequestedCertificate, AttestationResponse, CSRResponse, NocChain, OperationalNodeFoundData, ReadCommissioningInfo,
775 : AttestationErrorInfo, CommissioningErrorInfo, NetworkCommissioningStatusInfo, TimeZoneResponseInfo>
776 : {
777 0 : CommissioningReport() : stageCompleted(CommissioningStage::kError) {}
778 : CommissioningStage stageCompleted;
779 : };
780 : virtual CHIP_ERROR SetCommissioningParameters(const CommissioningParameters & params) = 0;
781 : virtual const CommissioningParameters & GetCommissioningParameters() const = 0;
782 : virtual void SetOperationalCredentialsDelegate(OperationalCredentialsDelegate * operationalCredentialsDelegate) = 0;
783 : virtual CHIP_ERROR StartCommissioning(DeviceCommissioner * commissioner, CommissioneeDeviceProxy * proxy) = 0;
784 : virtual CHIP_ERROR CommissioningStepFinished(CHIP_ERROR err, CommissioningReport report) = 0;
785 : };
786 :
787 : } // namespace Controller
788 : } // namespace chip
|