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