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