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