Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2024 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * Implementation of CHIP Device Controller, a common class
23 : * that implements discovery, pairing and provisioning of CHIP
24 : * devices.
25 : *
26 : */
27 :
28 : // module header, comes first
29 : #include <controller/CHIPDeviceController.h>
30 :
31 : #include <app-common/zap-generated/ids/Attributes.h>
32 : #include <app-common/zap-generated/ids/Clusters.h>
33 :
34 : #include <app/InteractionModelEngine.h>
35 : #include <app/OperationalSessionSetup.h>
36 : #include <app/server/Dnssd.h>
37 : #include <controller/CurrentFabricRemover.h>
38 : #include <controller/InvokeInteraction.h>
39 : #include <controller/WriteInteraction.h>
40 : #include <credentials/CHIPCert.h>
41 : #include <credentials/DeviceAttestationCredsProvider.h>
42 : #include <crypto/CHIPCryptoPAL.h>
43 : #include <lib/address_resolve/AddressResolve.h>
44 : #include <lib/core/CHIPCore.h>
45 : #include <lib/core/CHIPEncoding.h>
46 : #include <lib/core/CHIPSafeCasts.h>
47 : #include <lib/core/ErrorStr.h>
48 : #include <lib/core/NodeId.h>
49 : #include <lib/support/Base64.h>
50 : #include <lib/support/CHIPMem.h>
51 : #include <lib/support/CodeUtils.h>
52 : #include <lib/support/PersistentStorageMacros.h>
53 : #include <lib/support/SafeInt.h>
54 : #include <lib/support/ScopedMemoryBuffer.h>
55 : #include <lib/support/ThreadOperationalDataset.h>
56 : #include <lib/support/TimeUtils.h>
57 : #include <lib/support/logging/CHIPLogging.h>
58 : #include <messaging/ExchangeContext.h>
59 : #include <platform/LockTracker.h>
60 : #include <protocols/secure_channel/MessageCounterManager.h>
61 : #include <setup_payload/QRCodeSetupPayloadParser.h>
62 : #include <tracing/macros.h>
63 : #include <tracing/metric_event.h>
64 :
65 : #if CONFIG_NETWORK_LAYER_BLE
66 : #include <ble/Ble.h>
67 : #include <transport/raw/BLE.h>
68 : #endif
69 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
70 : #include <transport/raw/WiFiPAF.h>
71 : #endif
72 :
73 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
74 : #include <platform/internal/NFCCommissioningManager.h>
75 : #endif
76 :
77 : #include <algorithm>
78 : #include <array>
79 : #include <errno.h>
80 : #include <inttypes.h>
81 : #include <limits>
82 : #include <memory>
83 : #include <stdint.h>
84 : #include <stdlib.h>
85 : #include <string>
86 : #include <time.h>
87 :
88 : using namespace chip::app;
89 : using namespace chip::app::Clusters;
90 : using namespace chip::Inet;
91 : using namespace chip::System;
92 : using namespace chip::Transport;
93 : using namespace chip::Credentials;
94 : using namespace chip::Crypto;
95 : using namespace chip::Tracing;
96 :
97 : namespace chip {
98 : namespace Controller {
99 :
100 : using namespace chip::Encoding;
101 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
102 : using namespace chip::Protocols::UserDirectedCommissioning;
103 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
104 :
105 : using chip::AddressResolve::Resolver;
106 : using chip::AddressResolve::ResolveResult;
107 :
108 275 : DeviceController::DeviceController()
109 : {
110 25 : mState = State::NotInitialized;
111 25 : }
112 :
113 0 : CHIP_ERROR DeviceController::Init(ControllerInitParams params)
114 : {
115 0 : assertChipStackLockedByCurrentThread();
116 :
117 0 : VerifyOrReturnError(mState == State::NotInitialized, CHIP_ERROR_INCORRECT_STATE);
118 0 : VerifyOrReturnError(params.systemState != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
119 :
120 0 : VerifyOrReturnError(params.systemState->SystemLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
121 0 : VerifyOrReturnError(params.systemState->UDPEndPointManager() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
122 :
123 : #if CONFIG_NETWORK_LAYER_BLE
124 0 : VerifyOrReturnError(params.systemState->BleLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
125 : #endif
126 :
127 0 : VerifyOrReturnError(params.systemState->TransportMgr() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
128 :
129 0 : ReturnErrorOnFailure(mDNSResolver.Init(params.systemState->UDPEndPointManager()));
130 0 : mDNSResolver.SetDiscoveryDelegate(this);
131 0 : RegisterDeviceDiscoveryDelegate(params.deviceDiscoveryDelegate);
132 :
133 0 : mVendorId = params.controllerVendorId;
134 0 : if (params.operationalKeypair != nullptr || !params.controllerNOC.empty() || !params.controllerRCAC.empty())
135 : {
136 0 : ReturnErrorOnFailure(InitControllerNOCChain(params));
137 : }
138 0 : else if (params.fabricIndex.HasValue())
139 : {
140 0 : VerifyOrReturnError(params.systemState->Fabrics()->FabricCount() > 0, CHIP_ERROR_INVALID_ARGUMENT);
141 0 : if (params.systemState->Fabrics()->FindFabricWithIndex(params.fabricIndex.Value()) != nullptr)
142 : {
143 0 : mFabricIndex = params.fabricIndex.Value();
144 : }
145 : else
146 : {
147 0 : ChipLogError(Controller, "There is no fabric corresponding to the given fabricIndex");
148 0 : return CHIP_ERROR_INVALID_ARGUMENT;
149 : }
150 : }
151 :
152 0 : mSystemState = params.systemState->Retain();
153 0 : mState = State::Initialized;
154 :
155 0 : mRemoveFromFabricTableOnShutdown = params.removeFromFabricTableOnShutdown;
156 0 : mDeleteFromFabricTableOnShutdown = params.deleteFromFabricTableOnShutdown;
157 :
158 0 : if (GetFabricIndex() != kUndefinedFabricIndex)
159 : {
160 0 : ChipLogProgress(Controller,
161 : "Joined the fabric at index %d. Fabric ID is 0x" ChipLogFormatX64
162 : " (Compressed Fabric ID: " ChipLogFormatX64 ")",
163 : GetFabricIndex(), ChipLogValueX64(GetFabricId()), ChipLogValueX64(GetCompressedFabricId()));
164 : }
165 :
166 0 : return CHIP_NO_ERROR;
167 : }
168 :
169 0 : CHIP_ERROR DeviceController::InitControllerNOCChain(const ControllerInitParams & params)
170 : {
171 0 : FabricInfo newFabric;
172 0 : constexpr uint32_t chipCertAllocatedLen = kMaxCHIPCertLength;
173 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> rcacBuf;
174 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
175 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> nocBuf;
176 0 : Credentials::P256PublicKeySpan rootPublicKeySpan;
177 : FabricId fabricId;
178 : NodeId nodeId;
179 0 : bool hasExternallyOwnedKeypair = false;
180 0 : Crypto::P256Keypair * externalOperationalKeypair = nullptr;
181 0 : VendorId newFabricVendorId = params.controllerVendorId;
182 :
183 : // There are three possibilities here in terms of what happens with our
184 : // operational key:
185 : // 1) We have an externally owned operational keypair.
186 : // 2) We have an operational keypair that the fabric table should clone via
187 : // serialize/deserialize.
188 : // 3) We have no keypair at all, and the fabric table has been initialized
189 : // with a key store.
190 0 : if (params.operationalKeypair != nullptr)
191 : {
192 0 : hasExternallyOwnedKeypair = params.hasExternallyOwnedOperationalKeypair;
193 0 : externalOperationalKeypair = params.operationalKeypair;
194 : }
195 :
196 0 : VerifyOrReturnError(rcacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
197 0 : VerifyOrReturnError(icacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
198 0 : VerifyOrReturnError(nocBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
199 :
200 0 : MutableByteSpan rcacSpan(rcacBuf.Get(), chipCertAllocatedLen);
201 :
202 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerRCAC, rcacSpan));
203 0 : ReturnErrorOnFailure(Credentials::ExtractPublicKeyFromChipCert(rcacSpan, rootPublicKeySpan));
204 0 : Crypto::P256PublicKey rootPublicKey{ rootPublicKeySpan };
205 :
206 0 : MutableByteSpan icacSpan;
207 0 : if (params.controllerICAC.empty())
208 : {
209 0 : ChipLogProgress(Controller, "Intermediate CA is not needed");
210 : }
211 : else
212 : {
213 0 : icacSpan = MutableByteSpan(icacBuf.Get(), chipCertAllocatedLen);
214 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerICAC, icacSpan));
215 : }
216 :
217 0 : MutableByteSpan nocSpan = MutableByteSpan(nocBuf.Get(), chipCertAllocatedLen);
218 :
219 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerNOC, nocSpan));
220 0 : ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(nocSpan, &nodeId, &fabricId));
221 :
222 0 : auto * fabricTable = params.systemState->Fabrics();
223 0 : const FabricInfo * fabricInfo = nullptr;
224 :
225 : //
226 : // When multiple controllers are permitted on the same fabric, we need to find fabrics with
227 : // nodeId as an extra discriminant since we can have multiple FabricInfo objects that all
228 : // collide on the same fabric. Not doing so may result in a match with an existing FabricInfo
229 : // instance that matches the fabric in the provided NOC but is associated with a different NodeId
230 : // that is already in use by another active controller instance. That will effectively cause it
231 : // to change its identity inadvertently, which is not acceptable.
232 : //
233 : // TODO: Figure out how to clean up unreclaimed FabricInfos restored from persistent
234 : // storage that are not in use by active DeviceController instances. Also, figure out
235 : // how to reclaim FabricInfo slots when a DeviceController instance is deleted.
236 : //
237 0 : if (params.permitMultiControllerFabrics)
238 : {
239 0 : fabricInfo = fabricTable->FindIdentity(rootPublicKey, fabricId, nodeId);
240 : }
241 : else
242 : {
243 0 : fabricInfo = fabricTable->FindFabric(rootPublicKey, fabricId);
244 : }
245 :
246 0 : bool fabricFoundInTable = (fabricInfo != nullptr);
247 :
248 0 : FabricIndex fabricIndex = fabricFoundInTable ? fabricInfo->GetFabricIndex() : kUndefinedFabricIndex;
249 :
250 0 : CHIP_ERROR err = CHIP_NO_ERROR;
251 :
252 0 : auto advertiseOperational =
253 0 : params.enableServerInteractions ? FabricTable::AdvertiseIdentity::Yes : FabricTable::AdvertiseIdentity::No;
254 :
255 : //
256 : // We permit colliding fabrics when multiple controllers are present on the same logical fabric
257 : // since each controller is associated with a unique FabricInfo 'identity' object and consequently,
258 : // a unique FabricIndex.
259 : //
260 : // This sets a flag that will be cleared automatically when the fabric is committed/reverted later
261 : // in this function.
262 : //
263 0 : if (params.permitMultiControllerFabrics)
264 : {
265 0 : fabricTable->PermitCollidingFabrics();
266 : }
267 :
268 : // We have 4 cases to handle legacy usage of direct operational key injection
269 0 : if (externalOperationalKeypair)
270 : {
271 : // Cases 1 and 2: Injected operational keys
272 :
273 : // CASE 1: Fabric update with injected key
274 0 : if (fabricFoundInTable)
275 : {
276 0 : err = fabricTable->UpdatePendingFabricWithProvidedOpKey(fabricIndex, nocSpan, icacSpan, externalOperationalKeypair,
277 : hasExternallyOwnedKeypair, advertiseOperational);
278 : }
279 : else
280 : // CASE 2: New fabric with injected key
281 : {
282 0 : err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
283 0 : if (err == CHIP_NO_ERROR)
284 : {
285 0 : err = fabricTable->AddNewPendingFabricWithProvidedOpKey(nocSpan, icacSpan, newFabricVendorId,
286 : externalOperationalKeypair, hasExternallyOwnedKeypair,
287 : &fabricIndex, advertiseOperational);
288 : }
289 : }
290 : }
291 : else
292 : {
293 : // Cases 3 and 4: OperationalKeystore has the keys
294 :
295 : // CASE 3: Fabric update with operational keystore
296 0 : if (fabricFoundInTable)
297 : {
298 0 : VerifyOrReturnError(fabricTable->HasOperationalKeyForFabric(fabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
299 :
300 0 : err = fabricTable->UpdatePendingFabricWithOperationalKeystore(fabricIndex, nocSpan, icacSpan, advertiseOperational);
301 : }
302 : else
303 : // CASE 4: New fabric with operational keystore
304 : {
305 0 : err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
306 0 : if (err == CHIP_NO_ERROR)
307 : {
308 0 : err = fabricTable->AddNewPendingFabricWithOperationalKeystore(nocSpan, icacSpan, newFabricVendorId, &fabricIndex,
309 : advertiseOperational);
310 : }
311 :
312 0 : if (err == CHIP_NO_ERROR)
313 : {
314 : // Now that we know our planned fabric index, verify that the
315 : // keystore has a key for it.
316 0 : if (!fabricTable->HasOperationalKeyForFabric(fabricIndex))
317 : {
318 0 : err = CHIP_ERROR_KEY_NOT_FOUND;
319 : }
320 : }
321 : }
322 : }
323 :
324 : // Commit after setup, error-out on failure.
325 0 : if (err == CHIP_NO_ERROR)
326 : {
327 : // No need to revert on error: CommitPendingFabricData reverts internally on *any* error.
328 0 : err = fabricTable->CommitPendingFabricData();
329 : }
330 : else
331 : {
332 0 : fabricTable->RevertPendingFabricData();
333 : }
334 :
335 0 : ReturnErrorOnFailure(err);
336 0 : VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
337 :
338 0 : mFabricIndex = fabricIndex;
339 0 : mAdvertiseIdentity = advertiseOperational;
340 0 : return CHIP_NO_ERROR;
341 0 : }
342 :
343 0 : CHIP_ERROR DeviceController::UpdateControllerNOCChain(const ByteSpan & noc, const ByteSpan & icac,
344 : Crypto::P256Keypair * operationalKeypair,
345 : bool operationalKeypairExternalOwned)
346 : {
347 0 : VerifyOrReturnError(mFabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
348 0 : VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INTERNAL);
349 0 : FabricTable * fabricTable = mSystemState->Fabrics();
350 0 : CHIP_ERROR err = CHIP_NO_ERROR;
351 : FabricId fabricId;
352 : NodeId nodeId;
353 0 : CATValues oldCats;
354 0 : CATValues newCats;
355 0 : ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(noc, &nodeId, &fabricId));
356 0 : ReturnErrorOnFailure(fabricTable->FetchCATs(mFabricIndex, oldCats));
357 0 : ReturnErrorOnFailure(ExtractCATsFromOpCert(noc, newCats));
358 :
359 0 : bool needCloseSession = true;
360 0 : if (GetFabricInfo()->GetNodeId() == nodeId && oldCats == newCats)
361 : {
362 0 : needCloseSession = false;
363 : }
364 :
365 0 : if (operationalKeypair != nullptr)
366 : {
367 0 : err = fabricTable->UpdatePendingFabricWithProvidedOpKey(mFabricIndex, noc, icac, operationalKeypair,
368 : operationalKeypairExternalOwned, mAdvertiseIdentity);
369 : }
370 : else
371 : {
372 0 : VerifyOrReturnError(fabricTable->HasOperationalKeyForFabric(mFabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
373 0 : err = fabricTable->UpdatePendingFabricWithOperationalKeystore(mFabricIndex, noc, icac, mAdvertiseIdentity);
374 : }
375 :
376 0 : if (err == CHIP_NO_ERROR)
377 : {
378 0 : err = fabricTable->CommitPendingFabricData();
379 : }
380 : else
381 : {
382 0 : fabricTable->RevertPendingFabricData();
383 : }
384 :
385 0 : ReturnErrorOnFailure(err);
386 0 : if (needCloseSession)
387 : {
388 : // If the node id or CATs have changed, our existing CASE sessions are no longer valid,
389 : // because the other side will think anything coming over those sessions comes from our
390 : // old node ID, and the new CATs might not satisfy the ACL requirements of the other side.
391 0 : mSystemState->SessionMgr()->ExpireAllSessionsForFabric(mFabricIndex);
392 : }
393 0 : ChipLogProgress(Controller, "Controller NOC chain has updated");
394 0 : return CHIP_NO_ERROR;
395 : }
396 :
397 0 : void DeviceController::Shutdown()
398 : {
399 0 : assertChipStackLockedByCurrentThread();
400 :
401 0 : VerifyOrReturn(mState != State::NotInitialized);
402 :
403 : // If our state is initialialized it means mSystemState is valid,
404 : // and we can use it below before we release our reference to it.
405 0 : ChipLogDetail(Controller, "Shutting down the controller");
406 0 : mState = State::NotInitialized;
407 :
408 0 : if (mFabricIndex != kUndefinedFabricIndex)
409 : {
410 : // Shut down any subscription clients for this fabric.
411 0 : app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(mFabricIndex);
412 :
413 : // Shut down any ongoing CASE session activity we have. We're going to
414 : // assume that all sessions for our fabric belong to us here.
415 0 : mSystemState->CASESessionMgr()->ReleaseSessionsForFabric(mFabricIndex);
416 :
417 : // Shut down any bdx transfers we're acting as the server for.
418 0 : mSystemState->BDXTransferServer()->AbortTransfersForFabric(mFabricIndex);
419 :
420 : // TODO: The CASE session manager does not shut down existing CASE
421 : // sessions. It just shuts down any ongoing CASE session establishment
422 : // we're in the middle of as initiator. Maybe it should shut down
423 : // existing sessions too?
424 0 : mSystemState->SessionMgr()->ExpireAllSessionsForFabric(mFabricIndex);
425 :
426 0 : if (mDeleteFromFabricTableOnShutdown)
427 : {
428 0 : TEMPORARY_RETURN_IGNORED mSystemState->Fabrics()->Delete(mFabricIndex);
429 : }
430 0 : else if (mRemoveFromFabricTableOnShutdown)
431 : {
432 0 : mSystemState->Fabrics()->Forget(mFabricIndex);
433 : }
434 : }
435 :
436 0 : mSystemState->Release();
437 0 : mSystemState = nullptr;
438 :
439 0 : mDNSResolver.Shutdown();
440 0 : mDeviceDiscoveryDelegate = nullptr;
441 : }
442 :
443 0 : CHIP_ERROR DeviceController::GetPeerAddressAndPort(NodeId peerId, Inet::IPAddress & addr, uint16_t & port)
444 : {
445 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
446 0 : Transport::PeerAddress peerAddr;
447 0 : ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(peerId), peerAddr));
448 0 : addr = peerAddr.GetIPAddress();
449 0 : port = peerAddr.GetPort();
450 0 : return CHIP_NO_ERROR;
451 : }
452 :
453 0 : CHIP_ERROR DeviceController::GetPeerAddress(NodeId nodeId, Transport::PeerAddress & addr)
454 : {
455 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
456 0 : ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(nodeId), addr));
457 :
458 0 : return CHIP_NO_ERROR;
459 : }
460 :
461 0 : CHIP_ERROR DeviceController::ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt,
462 : Spake2pVerifier & outVerifier)
463 : {
464 0 : ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(outVerifier, iterations, salt, /* useRandomPIN= */ false, setupPincode));
465 :
466 0 : return CHIP_NO_ERROR;
467 : }
468 :
469 0 : ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams()
470 : {
471 : return ControllerDeviceInitParams{
472 0 : .sessionManager = mSystemState->SessionMgr(),
473 0 : .exchangeMgr = mSystemState->ExchangeMgr(),
474 0 : };
475 : }
476 :
477 13 : DeviceCommissioner::DeviceCommissioner() :
478 13 : mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this),
479 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
480 13 : mOnDeviceConnectionRetryCallback(OnDeviceConnectionRetryFn, this),
481 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
482 13 : mDeviceAttestationInformationVerificationCallback(OnDeviceAttestationInformationVerification, this),
483 26 : mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this)
484 : {
485 : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
486 : (void) mPeerAdminJFAdminClusterEndpointId;
487 : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
488 13 : }
489 :
490 0 : CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params)
491 : {
492 0 : VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
493 0 : mOperationalCredentialsDelegate = params.operationalCredentialsDelegate;
494 0 : ReturnErrorOnFailure(DeviceController::Init(params));
495 :
496 0 : mPairingDelegate = params.pairingDelegate;
497 :
498 : // Configure device attestation validation
499 0 : mDeviceAttestationVerifier = params.deviceAttestationVerifier;
500 0 : if (mDeviceAttestationVerifier == nullptr)
501 : {
502 0 : mDeviceAttestationVerifier = Credentials::GetDeviceAttestationVerifier();
503 0 : if (mDeviceAttestationVerifier == nullptr)
504 : {
505 0 : ChipLogError(Controller,
506 : "Missing DeviceAttestationVerifier configuration at DeviceCommissioner init and none set with "
507 : "Credentials::SetDeviceAttestationVerifier()!");
508 0 : return CHIP_ERROR_INVALID_ARGUMENT;
509 : }
510 :
511 : // We fell back on a default from singleton accessor.
512 0 : ChipLogProgress(Controller,
513 : "*** Missing DeviceAttestationVerifier configuration at DeviceCommissioner init: using global default, "
514 : "consider passing one in CommissionerInitParams.");
515 : }
516 :
517 0 : if (params.defaultCommissioner != nullptr)
518 : {
519 0 : mDefaultCommissioner = params.defaultCommissioner;
520 : }
521 : // Otherwise leave it pointing to mAutoCommissioner.
522 :
523 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
524 : mUdcTransportMgr = chip::Platform::New<UdcTransportMgr>();
525 : ReturnErrorOnFailure(mUdcTransportMgr->Init(Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
526 : .SetAddressType(Inet::IPAddressType::kIPv6)
527 : .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
528 : #if INET_CONFIG_ENABLE_IPV4
529 : ,
530 : Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
531 : .SetAddressType(Inet::IPAddressType::kIPv4)
532 : .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
533 : #endif // INET_CONFIG_ENABLE_IPV4
534 : ));
535 :
536 : mUdcServer = chip::Platform::New<UserDirectedCommissioningServer>();
537 : mUdcTransportMgr->SetSessionManager(mUdcServer);
538 : mUdcServer->SetTransportManager(mUdcTransportMgr);
539 :
540 : mUdcServer->SetInstanceNameResolver(this);
541 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
542 :
543 0 : mSetUpCodePairer.SetSystemLayer(mSystemState->SystemLayer());
544 : #if CONFIG_NETWORK_LAYER_BLE
545 0 : mSetUpCodePairer.SetBleLayer(mSystemState->BleLayer());
546 : #endif // CONFIG_NETWORK_LAYER_BLE
547 :
548 0 : return CHIP_NO_ERROR;
549 : }
550 :
551 0 : void DeviceCommissioner::Shutdown()
552 : {
553 0 : VerifyOrReturn(mState != State::NotInitialized);
554 :
555 0 : ChipLogDetail(Controller, "Shutting down the commissioner");
556 :
557 0 : mSetUpCodePairer.StopPairing();
558 :
559 : // Check to see if pairing in progress before shutting down
560 0 : CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
561 0 : if (device != nullptr && device->IsSessionSetupInProgress())
562 : {
563 0 : ChipLogDetail(Controller, "Setup in progress, stopping setup before shutting down");
564 0 : OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
565 : }
566 :
567 0 : CancelCommissioningInteractions();
568 :
569 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
570 : if (mUdcTransportMgr != nullptr)
571 : {
572 : chip::Platform::Delete(mUdcTransportMgr);
573 : mUdcTransportMgr = nullptr;
574 : }
575 : if (mUdcServer != nullptr)
576 : {
577 : mUdcServer->SetInstanceNameResolver(nullptr);
578 : chip::Platform::Delete(mUdcServer);
579 : mUdcServer = nullptr;
580 : }
581 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
582 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
583 0 : WiFiPAF::WiFiPAFLayer::GetWiFiPAFLayer().Shutdown();
584 : #endif
585 :
586 : // Release everything from the commissionee device pool here.
587 : // Make sure to use ReleaseCommissioneeDevice so we don't keep dangling
588 : // pointers to the device objects.
589 0 : mCommissioneeDevicePool.ForEachActiveObject([this](auto * commissioneeDevice) {
590 0 : ReleaseCommissioneeDevice(commissioneeDevice);
591 0 : return Loop::Continue;
592 : });
593 :
594 0 : DeviceController::Shutdown();
595 : }
596 :
597 0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(NodeId id)
598 : {
599 : MATTER_TRACE_SCOPE("FindCommissioneeDevice", "DeviceCommissioner");
600 0 : CommissioneeDeviceProxy * foundDevice = nullptr;
601 0 : mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
602 0 : if (deviceProxy->GetDeviceId() == id || deviceProxy->GetTemporaryCommissioningId() == id)
603 : {
604 0 : foundDevice = deviceProxy;
605 0 : return Loop::Break;
606 : }
607 0 : return Loop::Continue;
608 : });
609 :
610 0 : return foundDevice;
611 : }
612 :
613 0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(const Transport::PeerAddress & peerAddress)
614 : {
615 0 : CommissioneeDeviceProxy * foundDevice = nullptr;
616 0 : mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
617 0 : if (deviceProxy->GetPeerAddress() == peerAddress)
618 : {
619 0 : foundDevice = deviceProxy;
620 0 : return Loop::Break;
621 : }
622 0 : return Loop::Continue;
623 : });
624 :
625 0 : return foundDevice;
626 : }
627 :
628 0 : void DeviceCommissioner::ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device)
629 : {
630 : #if CONFIG_NETWORK_LAYER_BLE
631 0 : if (mSystemState->BleLayer() != nullptr && device->GetDeviceTransportType() == Transport::Type::kBle)
632 : {
633 : // We only support one BLE connection, so if this is BLE, close it
634 0 : ChipLogProgress(Discovery, "Closing all BLE connections");
635 0 : mSystemState->BleLayer()->CloseAllBleConnections();
636 : }
637 : #endif
638 :
639 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
640 : Nfc::NFCReaderTransport * readerTransport = DeviceLayer::Internal::NFCCommissioningMgr().GetNFCReaderTransport();
641 : if (readerTransport)
642 : {
643 : ChipLogProgress(Controller, "Stopping discovery of all NFC tags");
644 : TEMPORARY_RETURN_IGNORED readerTransport->StopDiscoveringTags();
645 : }
646 : #endif
647 :
648 : // Make sure that there will be no dangling pointer
649 0 : if (mDeviceInPASEEstablishment == device)
650 : {
651 0 : mDeviceInPASEEstablishment = nullptr;
652 : }
653 0 : if (mDeviceBeingCommissioned == device)
654 : {
655 0 : mDeviceBeingCommissioned = nullptr;
656 : }
657 :
658 : // Release the commissionee device after we have nulled out our pointers,
659 : // because that can call back in to us with error notifications as the
660 : // session is released.
661 0 : mCommissioneeDevicePool.ReleaseObject(device);
662 0 : }
663 :
664 0 : CHIP_ERROR DeviceCommissioner::GetDeviceBeingCommissioned(NodeId deviceId, CommissioneeDeviceProxy ** out_device)
665 : {
666 0 : VerifyOrReturnError(out_device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
667 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(deviceId);
668 :
669 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
670 :
671 0 : *out_device = device;
672 :
673 0 : return CHIP_NO_ERROR;
674 : }
675 :
676 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, const CommissioningParameters & params,
677 : DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData,
678 : Optional<SetUpCodePairer::ThreadMeshcopCommissionParameters> meshcopCommissionParams)
679 : {
680 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
681 : #if CHIP_SUPPORT_THREAD_MESHCOP
682 0 : if (meshcopCommissionParams.HasValue())
683 : {
684 0 : mSetUpCodePairer.SetThreadMeshcopCommissionParamsAndProxy(meshcopCommissionParams.Value(), &mThreadMeshcopCommissionProxy);
685 : }
686 : #endif
687 0 : ReturnErrorOnFailure(mDefaultCommissioner->SetCommissioningParameters(params));
688 :
689 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
690 0 : resolutionData);
691 : }
692 :
693 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
694 : Optional<Dnssd::CommonResolutionData> resolutionData)
695 : {
696 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
697 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
698 0 : resolutionData);
699 : }
700 :
701 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params)
702 : {
703 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
704 0 : ReturnErrorOnFailureWithMetric(kMetricDeviceCommissionerCommission, EstablishPASEConnection(remoteDeviceId, params));
705 0 : auto errorCode = Commission(remoteDeviceId);
706 0 : VerifyOrDoWithMetric(kMetricDeviceCommissionerCommission, CHIP_NO_ERROR == errorCode, errorCode);
707 0 : return errorCode;
708 : }
709 :
710 : #if CHIP_SUPPORT_THREAD_MESHCOP
711 0 : CHIP_ERROR DeviceCommissioner::PairThreadMeshcop(RendezvousParameters & rendezvousParams,
712 : CommissioningParameters & commissioningParams)
713 : {
714 0 : VerifyOrReturnError(rendezvousParams.GetSetupDiscriminator().has_value(), CHIP_ERROR_INVALID_ARGUMENT);
715 0 : VerifyOrReturnError(commissioningParams.GetThreadOperationalDataset().HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
716 0 : auto discriminator = rendezvousParams.GetSetupDiscriminator().value();
717 0 : Thread::DiscoveryCode code;
718 0 : if (rendezvousParams.GetSetupDiscriminator().value().IsShortDiscriminator())
719 : {
720 0 : code = Thread::DiscoveryCode(discriminator.GetShortValue());
721 0 : ChipLogProgress(Controller, "Discovery code from short discriminator: 0x%" PRIx64, code.AsUInt64());
722 : }
723 : else
724 : {
725 0 : code = Thread::DiscoveryCode(discriminator.GetLongValue());
726 0 : ChipLogProgress(Controller, "Discovery code from long discriminator: 0x%" PRIx64, code.AsUInt64());
727 : }
728 :
729 : uint8_t pskcBuffer[Thread::kSizePSKc];
730 0 : ByteSpan pskc(pskcBuffer);
731 : {
732 0 : Thread::OperationalDatasetView dataset;
733 0 : ReturnErrorOnFailure(dataset.Init(commissioningParams.GetThreadOperationalDataset().Value()));
734 :
735 0 : ReturnErrorOnFailure(dataset.GetPSKc(pskcBuffer));
736 : }
737 :
738 : {
739 0 : Dnssd::DiscoveredNodeData discoveredNodeData;
740 0 : ReturnErrorOnFailure(mThreadMeshcopCommissionProxy.Discover(pskc, rendezvousParams.GetPeerAddress(), code, discriminator,
741 : discoveredNodeData, 30));
742 :
743 0 : ChipLogProgress(Controller, "Joiner discovered");
744 0 : OnNodeDiscovered(discoveredNodeData);
745 0 : }
746 0 : return CHIP_NO_ERROR;
747 : }
748 : #endif // CHIP_SUPPORT_THREAD_MESHCOP
749 :
750 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams,
751 : CommissioningParameters & commissioningParams)
752 : {
753 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
754 : #if CHIP_SUPPORT_THREAD_MESHCOP
755 0 : if (rendezvousParams.GetPeerAddress().GetTransportType() == Transport::Type::kThreadMeshcop)
756 : {
757 0 : return PairThreadMeshcop(rendezvousParams, commissioningParams);
758 : }
759 : #endif
760 0 : ReturnErrorOnFailureWithMetric(kMetricDeviceCommissionerCommission, EstablishPASEConnection(remoteDeviceId, rendezvousParams));
761 0 : auto errorCode = Commission(remoteDeviceId, commissioningParams);
762 0 : VerifyOrDoWithMetric(kMetricDeviceCommissionerCommission, CHIP_NO_ERROR == errorCode, errorCode);
763 0 : return errorCode;
764 : }
765 :
766 : CHIP_ERROR
767 0 : DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
768 : Optional<Dnssd::CommonResolutionData> resolutionData,
769 : Optional<SetUpCodePairer::ThreadMeshcopCommissionParameters> meshcopCommissionParams)
770 : {
771 : MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
772 : #if CHIP_SUPPORT_THREAD_MESHCOP
773 0 : if (meshcopCommissionParams.HasValue())
774 : {
775 0 : mSetUpCodePairer.SetThreadMeshcopCommissionParamsAndProxy(meshcopCommissionParams.Value(), &mThreadMeshcopCommissionProxy);
776 : }
777 : #endif
778 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kPaseOnly, discoveryType,
779 0 : resolutionData);
780 : }
781 :
782 0 : CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, RendezvousParameters & params)
783 : {
784 : MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
785 : MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissionerPASESession);
786 :
787 0 : CHIP_ERROR err = CHIP_NO_ERROR;
788 0 : CommissioneeDeviceProxy * device = nullptr;
789 0 : CommissioneeDeviceProxy * current = nullptr;
790 0 : Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
791 :
792 0 : Messaging::ExchangeContext * exchangeCtxt = nullptr;
793 0 : Optional<SessionHandle> session;
794 :
795 0 : VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
796 0 : VerifyOrExit(mDeviceInPASEEstablishment == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
797 :
798 : // TODO(#13940): We need to specify the peer address for BLE transport in bindings.
799 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle ||
800 0 : params.GetPeerAddress().GetTransportType() == Transport::Type::kUndefined)
801 : {
802 : #if CONFIG_NETWORK_LAYER_BLE
803 : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
804 : ConnectBleTransportToSelf();
805 : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
806 0 : if (!params.HasBleLayer())
807 : {
808 0 : params.SetPeerAddress(Transport::PeerAddress::BLE());
809 : }
810 0 : peerAddress = Transport::PeerAddress::BLE();
811 : #endif // CONFIG_NETWORK_LAYER_BLE
812 : }
813 0 : else if (params.GetPeerAddress().GetTransportType() == Transport::Type::kTcp ||
814 0 : params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
815 : {
816 0 : peerAddress = Transport::PeerAddress::UDP(params.GetPeerAddress().GetIPAddress(), params.GetPeerAddress().GetPort(),
817 0 : params.GetPeerAddress().GetInterface());
818 : }
819 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
820 0 : else if (params.GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF)
821 : {
822 0 : peerAddress = Transport::PeerAddress::WiFiPAF(remoteDeviceId);
823 : }
824 : #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
825 :
826 0 : current = FindCommissioneeDevice(peerAddress);
827 0 : if (current != nullptr)
828 : {
829 0 : if (current->GetDeviceId() == remoteDeviceId)
830 : {
831 : // We might be able to just reuse its connection if it has one or is
832 : // working on one.
833 0 : if (current->IsSecureConnected())
834 : {
835 0 : if (mPairingDelegate)
836 : {
837 : // We already have an open secure session to this device, call the callback immediately and early return.
838 : // We don't know what the right RendezvousParameters are here.
839 0 : mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR, std::nullopt, std::nullopt);
840 : }
841 : MATTER_LOG_METRIC_END(kMetricDeviceCommissionerPASESession, CHIP_NO_ERROR);
842 0 : return CHIP_NO_ERROR;
843 : }
844 0 : if (current->IsSessionSetupInProgress())
845 : {
846 : // We're not connected yet, but we're in the process of connecting. Pairing delegate will get a callback when
847 : // connection completes
848 0 : return CHIP_NO_ERROR;
849 : }
850 : }
851 :
852 : // Either the consumer wants to assign a different device id to this
853 : // peer address now (so we can't reuse the commissionee device we have
854 : // already) or something has gone strange. Delete the old device, try
855 : // again.
856 0 : ChipLogError(Controller, "Found unconnected device, removing");
857 0 : ReleaseCommissioneeDevice(current);
858 : }
859 :
860 0 : device = mCommissioneeDevicePool.CreateObject();
861 0 : VerifyOrExit(device != nullptr, err = CHIP_ERROR_NO_MEMORY);
862 :
863 0 : mDeviceInPASEEstablishment = device;
864 0 : device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress);
865 0 : device->UpdateDeviceData(params.GetPeerAddress(), params.GetMRPConfig());
866 :
867 : #if CONFIG_NETWORK_LAYER_BLE
868 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle)
869 : {
870 0 : if (params.HasConnectionObject())
871 : {
872 0 : SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetConnectionObject()));
873 : }
874 0 : else if (params.HasDiscoveredObject())
875 : {
876 : // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
877 : // for later.
878 0 : mRendezvousParametersForDeviceDiscoveredOverBle = params;
879 0 : ExitNow(err = mSystemState->BleLayer()->NewBleConnectionByObject(
880 : params.GetDiscoveredObject(), this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError));
881 : }
882 0 : else if (params.GetSetupDiscriminator().has_value())
883 : {
884 : // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
885 : // for later.
886 0 : mRendezvousParametersForDeviceDiscoveredOverBle = params;
887 0 : auto setupDiscriminator = params.GetSetupDiscriminator();
888 0 : VerifyOrExit(setupDiscriminator.has_value(), err = CHIP_ERROR_INVALID_ARGUMENT);
889 0 : ExitNow(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(
890 : setupDiscriminator.value(), this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError));
891 : }
892 : else
893 : {
894 0 : ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT);
895 : }
896 : }
897 : #endif
898 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
899 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kWiFiPAF)
900 : {
901 0 : if (DeviceLayer::ConnectivityMgr().GetWiFiPAF()->GetWiFiPAFState() != WiFiPAF::State::kConnected)
902 : {
903 0 : ChipLogProgress(Controller, "WiFi-PAF: Subscribing to the NAN-USD devices, nodeId: %" PRIu64,
904 : params.GetPeerAddress().GetRemoteId());
905 0 : mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = params;
906 0 : auto nodeId = params.GetPeerAddress().GetRemoteId();
907 0 : const SetupDiscriminator connDiscriminator(params.GetSetupDiscriminator().value());
908 0 : VerifyOrReturnValue(!connDiscriminator.IsShortDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT,
909 : ChipLogError(Controller, "Error, Long discriminator is required"));
910 0 : uint16_t discriminator = connDiscriminator.GetLongValue();
911 0 : WiFiPAF::WiFiPAFSession sessionInfo = { .role = WiFiPAF::WiFiPafRole::kWiFiPafRole_Subscriber,
912 : .nodeId = nodeId,
913 0 : .discriminator = discriminator };
914 0 : ReturnErrorOnFailure(
915 : DeviceLayer::ConnectivityMgr().GetWiFiPAF()->AddPafSession(WiFiPAF::PafInfoAccess::kAccNodeInfo, sessionInfo));
916 0 : ExitNow(err = DeviceLayer::ConnectivityMgr().WiFiPAFSubscribe(discriminator, reinterpret_cast<void *>(this),
917 : OnWiFiPAFSubscribeComplete, OnWiFiPAFSubscribeError));
918 : }
919 : }
920 : #endif
921 0 : session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), params.GetMRPConfig());
922 0 : VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY);
923 :
924 : // Allocate the exchange immediately before calling PASESession::Pair.
925 : //
926 : // PASESession::Pair takes ownership of the exchange and will free it on
927 : // error, but can only do this if it is actually called. Allocating the
928 : // exchange context right before calling Pair ensures that if allocation
929 : // succeeds, PASESession has taken ownership.
930 0 : exchangeCtxt = mSystemState->ExchangeMgr()->NewContext(session.Value(), &device->GetPairing());
931 0 : VerifyOrExit(exchangeCtxt != nullptr, err = CHIP_ERROR_INTERNAL);
932 :
933 0 : err = device->GetPairing().Pair(*mSystemState->SessionMgr(), params.GetSetupPINCode(), GetLocalMRPConfig(), exchangeCtxt, this);
934 0 : SuccessOrExit(err);
935 :
936 0 : mRendezvousParametersForPASEEstablishment = params;
937 :
938 0 : exit:
939 0 : if (err != CHIP_NO_ERROR)
940 : {
941 0 : if (device != nullptr)
942 : {
943 0 : ReleaseCommissioneeDevice(device);
944 : }
945 : MATTER_LOG_METRIC_END(kMetricDeviceCommissionerPASESession, err);
946 : }
947 :
948 0 : return err;
949 0 : }
950 :
951 : #if CONFIG_NETWORK_LAYER_BLE
952 0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
953 : {
954 0 : auto self = static_cast<DeviceCommissioner *>(appState);
955 0 : auto device = self->mDeviceInPASEEstablishment;
956 :
957 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
958 : {
959 0 : auto remoteId = device->GetDeviceId();
960 :
961 0 : auto params = self->mRendezvousParametersForDeviceDiscoveredOverBle;
962 0 : params.SetConnectionObject(connObj);
963 0 : self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
964 :
965 0 : self->ReleaseCommissioneeDevice(device);
966 0 : LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params));
967 : }
968 0 : }
969 :
970 0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
971 : {
972 0 : auto self = static_cast<DeviceCommissioner *>(appState);
973 0 : auto device = self->mDeviceInPASEEstablishment;
974 :
975 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
976 : {
977 0 : self->ReleaseCommissioneeDevice(device);
978 0 : self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
979 :
980 : // Callback is required when BLE discovery fails, otherwise the caller will always be in a suspended state
981 : // A better way to handle it should define a new error code
982 0 : if (self->mPairingDelegate != nullptr)
983 : {
984 0 : self->mPairingDelegate->OnPairingComplete(err, std::nullopt, std::nullopt);
985 : }
986 : }
987 0 : }
988 : #endif // CONFIG_NETWORK_LAYER_BLE
989 :
990 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
991 0 : void DeviceCommissioner::OnWiFiPAFSubscribeComplete(void * appState)
992 : {
993 0 : auto self = reinterpret_cast<DeviceCommissioner *>(appState);
994 0 : auto device = self->mDeviceInPASEEstablishment;
995 :
996 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF)
997 : {
998 0 : ChipLogProgress(Controller, "WiFi-PAF: Subscription Completed, dev_id = %" PRIu64, device->GetDeviceId());
999 0 : auto remoteId = device->GetDeviceId();
1000 0 : auto params = self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF;
1001 :
1002 0 : self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = RendezvousParameters();
1003 0 : self->ReleaseCommissioneeDevice(device);
1004 0 : LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params));
1005 : }
1006 0 : }
1007 :
1008 0 : void DeviceCommissioner::OnWiFiPAFSubscribeError(void * appState, CHIP_ERROR err)
1009 : {
1010 0 : auto self = (DeviceCommissioner *) appState;
1011 0 : auto device = self->mDeviceInPASEEstablishment;
1012 :
1013 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kWiFiPAF)
1014 : {
1015 0 : ChipLogError(Controller, "WiFi-PAF: Subscription Error, id = %" PRIu64 ", err = %" CHIP_ERROR_FORMAT, device->GetDeviceId(),
1016 : err.Format());
1017 0 : self->ReleaseCommissioneeDevice(device);
1018 0 : self->mRendezvousParametersForDeviceDiscoveredOverWiFiPAF = RendezvousParameters();
1019 0 : if (self->mPairingDelegate != nullptr)
1020 : {
1021 0 : self->mPairingDelegate->OnPairingComplete(err, std::nullopt, std::nullopt);
1022 : }
1023 : }
1024 0 : }
1025 : #endif
1026 :
1027 0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningParameters & params)
1028 : {
1029 0 : ReturnErrorOnFailureWithMetric(kMetricDeviceCommissionerCommission, mDefaultCommissioner->SetCommissioningParameters(params));
1030 0 : auto errorCode = Commission(remoteDeviceId);
1031 0 : VerifyOrDoWithMetric(kMetricDeviceCommissionerCommission, CHIP_NO_ERROR == errorCode, errorCode);
1032 0 : return errorCode;
1033 : }
1034 :
1035 0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId)
1036 : {
1037 : MATTER_TRACE_SCOPE("Commission", "DeviceCommissioner");
1038 :
1039 : #if CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
1040 : // Reset fallback from any previous commissioning session
1041 : mFallbackOperationalResolveResult.ClearValue();
1042 : #endif // CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
1043 :
1044 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
1045 0 : if (device == nullptr || (!device->IsSecureConnected() && !device->IsSessionSetupInProgress()))
1046 : {
1047 0 : ChipLogError(Controller, "Invalid device for commissioning " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
1048 0 : return CHIP_ERROR_INCORRECT_STATE;
1049 : }
1050 0 : if (!device->IsSecureConnected() && device != mDeviceInPASEEstablishment)
1051 : {
1052 : // We should not end up in this state because we won't attempt to establish more than one connection at a time.
1053 0 : ChipLogError(Controller, "Device is not connected and not being paired " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
1054 0 : return CHIP_ERROR_INCORRECT_STATE;
1055 : }
1056 :
1057 0 : if (mCommissioningStage != CommissioningStage::kSecurePairing)
1058 : {
1059 0 : ChipLogError(Controller, "Commissioning already in progress (stage '%s') - not restarting",
1060 : StageToString(mCommissioningStage));
1061 0 : return CHIP_ERROR_INCORRECT_STATE;
1062 : }
1063 :
1064 0 : ChipLogProgress(Controller, "Commission called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
1065 :
1066 0 : mDefaultCommissioner->SetOperationalCredentialsDelegate(mOperationalCredentialsDelegate);
1067 0 : if (device->IsSecureConnected())
1068 : {
1069 : MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissionerCommission);
1070 0 : ReturnErrorOnFailure(mDefaultCommissioner->StartCommissioning(this, device));
1071 : }
1072 : else
1073 : {
1074 0 : mRunCommissioningAfterConnection = true;
1075 : }
1076 0 : return CHIP_NO_ERROR;
1077 : }
1078 :
1079 : CHIP_ERROR
1080 0 : DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * device,
1081 : Credentials::AttestationVerificationResult attestationResult)
1082 : {
1083 : MATTER_TRACE_SCOPE("continueCommissioningDevice", "DeviceCommissioner");
1084 :
1085 0 : if (device == nullptr || device != mDeviceBeingCommissioned)
1086 : {
1087 0 : ChipLogError(Controller, "Invalid device for commissioning %p", device);
1088 0 : return CHIP_ERROR_INCORRECT_STATE;
1089 : }
1090 0 : CommissioneeDeviceProxy * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
1091 0 : if (commissioneeDevice == nullptr)
1092 : {
1093 0 : ChipLogError(Controller, "Couldn't find commissionee device");
1094 0 : return CHIP_ERROR_INCORRECT_STATE;
1095 : }
1096 0 : if (!commissioneeDevice->IsSecureConnected() || commissioneeDevice != mDeviceBeingCommissioned)
1097 : {
1098 0 : ChipLogError(Controller, "Invalid device for commissioning after attestation failure: 0x" ChipLogFormatX64,
1099 : ChipLogValueX64(commissioneeDevice->GetDeviceId()));
1100 0 : return CHIP_ERROR_INCORRECT_STATE;
1101 : }
1102 :
1103 0 : if (mCommissioningStage != CommissioningStage::kAttestationRevocationCheck)
1104 : {
1105 0 : ChipLogError(Controller, "Commissioning is not attestation verification phase");
1106 0 : return CHIP_ERROR_INCORRECT_STATE;
1107 : }
1108 :
1109 0 : ChipLogProgress(Controller, "Continuing commissioning after attestation failure for device ID 0x" ChipLogFormatX64,
1110 : ChipLogValueX64(commissioneeDevice->GetDeviceId()));
1111 :
1112 0 : if (attestationResult != AttestationVerificationResult::kSuccess)
1113 : {
1114 0 : ChipLogError(Controller, "Client selected error: %u for failed 'Attestation Information' for device",
1115 : to_underlying(attestationResult));
1116 :
1117 0 : CommissioningDelegate::CommissioningReport report;
1118 0 : report.Set<AttestationErrorInfo>(attestationResult);
1119 0 : CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1120 0 : }
1121 : else
1122 : {
1123 0 : ChipLogProgress(Controller, "Overriding attestation failure per client and continuing commissioning");
1124 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1125 : }
1126 0 : return CHIP_NO_ERROR;
1127 : }
1128 :
1129 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
1130 : CHIP_ERROR DeviceCommissioner::ContinueCommissioningAfterConnectNetworkRequest(NodeId remoteDeviceId)
1131 : {
1132 : MATTER_TRACE_SCOPE("continueCommissioningAfterConnectNetworkRequest", "DeviceCommissioner");
1133 :
1134 : // Move to kEvictPreviousCaseSessions stage since the next stage will be to find the device
1135 : // on the operational network
1136 : mCommissioningStage = CommissioningStage::kEvictPreviousCaseSessions;
1137 :
1138 : // Setup device being commissioned
1139 : CommissioneeDeviceProxy * device = nullptr;
1140 : if (!mDeviceBeingCommissioned)
1141 : {
1142 : device = mCommissioneeDevicePool.CreateObject();
1143 : if (!device)
1144 : return CHIP_ERROR_NO_MEMORY;
1145 :
1146 : Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
1147 : device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress);
1148 : mDeviceBeingCommissioned = device;
1149 : }
1150 :
1151 : mDefaultCommissioner->SetOperationalCredentialsDelegate(mOperationalCredentialsDelegate);
1152 :
1153 : ChipLogProgress(Controller, "Continuing commissioning after connect to network complete for device ID 0x" ChipLogFormatX64,
1154 : ChipLogValueX64(remoteDeviceId));
1155 :
1156 : MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioningOperationalSetup);
1157 : CHIP_ERROR err = mDefaultCommissioner->StartCommissioning(this, device);
1158 : if (err != CHIP_NO_ERROR)
1159 : {
1160 : MATTER_LOG_METRIC_END(kMetricDeviceCommissioningOperationalSetup, err);
1161 : }
1162 : return err;
1163 : }
1164 : #endif
1165 :
1166 0 : CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId)
1167 : {
1168 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1169 0 : VerifyOrReturnError(remoteDeviceId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
1170 :
1171 0 : ChipLogProgress(Controller, "StopPairing called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
1172 :
1173 : // If we're still in the process of discovering the device, just stop the SetUpCodePairer
1174 0 : if (mSetUpCodePairer.StopPairing(remoteDeviceId))
1175 : {
1176 0 : mRunCommissioningAfterConnection = false;
1177 0 : OnSessionEstablishmentError(CHIP_ERROR_CANCELLED);
1178 0 : return CHIP_NO_ERROR;
1179 : }
1180 :
1181 : // Otherwise we might be pairing and / or commissioning it.
1182 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
1183 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
1184 :
1185 0 : if (mDeviceBeingCommissioned == device)
1186 : {
1187 0 : CancelCommissioningInteractions();
1188 0 : CommissioningStageComplete(CHIP_ERROR_CANCELLED);
1189 : }
1190 : else
1191 : {
1192 0 : ReleaseCommissioneeDevice(device);
1193 : }
1194 0 : return CHIP_NO_ERROR;
1195 : }
1196 :
1197 0 : void DeviceCommissioner::CancelCommissioningInteractions()
1198 : {
1199 0 : if (mReadClient)
1200 : {
1201 0 : ChipLogDetail(Controller, "Cancelling read request for step '%s'", StageToString(mCommissioningStage));
1202 0 : mReadClient.reset(); // destructor cancels
1203 0 : mAttributeCache.reset();
1204 : }
1205 0 : if (mInvokeCancelFn)
1206 : {
1207 0 : ChipLogDetail(Controller, "Cancelling command invocation for step '%s'", StageToString(mCommissioningStage));
1208 0 : mInvokeCancelFn();
1209 0 : mInvokeCancelFn = nullptr;
1210 : }
1211 0 : if (mWriteCancelFn)
1212 : {
1213 0 : ChipLogDetail(Controller, "Cancelling write request for step '%s'", StageToString(mCommissioningStage));
1214 0 : mWriteCancelFn();
1215 0 : mWriteCancelFn = nullptr;
1216 : }
1217 0 : if (mOnDeviceConnectedCallback.IsRegistered())
1218 : {
1219 0 : ChipLogDetail(Controller, "Cancelling CASE setup for step '%s'", StageToString(mCommissioningStage));
1220 0 : CancelCASECallbacks();
1221 : }
1222 0 : }
1223 :
1224 0 : void DeviceCommissioner::CancelCASECallbacks()
1225 : {
1226 0 : mOnDeviceConnectedCallback.Cancel();
1227 0 : mOnDeviceConnectionFailureCallback.Cancel();
1228 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
1229 0 : mOnDeviceConnectionRetryCallback.Cancel();
1230 : #endif
1231 0 : }
1232 :
1233 0 : CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId)
1234 : {
1235 : MATTER_TRACE_SCOPE("UnpairDevice", "DeviceCommissioner");
1236 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1237 :
1238 0 : return AutoCurrentFabricRemover::RemoveCurrentFabric(this, remoteDeviceId);
1239 : }
1240 :
1241 1 : void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status)
1242 : {
1243 1 : if (mDeviceInPASEEstablishment != nullptr)
1244 : {
1245 : // Release the commissionee device. For BLE, this is stored,
1246 : // for IP commissioning, we have taken a reference to the
1247 : // operational node to send the completion command.
1248 0 : ReleaseCommissioneeDevice(mDeviceInPASEEstablishment);
1249 :
1250 0 : if (mPairingDelegate != nullptr)
1251 : {
1252 0 : mPairingDelegate->OnPairingComplete(status, std::nullopt, std::nullopt);
1253 : }
1254 : }
1255 1 : }
1256 :
1257 1 : void DeviceCommissioner::OnSessionEstablishmentError(CHIP_ERROR err)
1258 : {
1259 : MATTER_LOG_METRIC_END(kMetricDeviceCommissionerPASESession, err);
1260 :
1261 1 : mRendezvousParametersForPASEEstablishment.reset();
1262 :
1263 1 : if (mPairingDelegate != nullptr)
1264 : {
1265 0 : mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingFailed);
1266 : }
1267 :
1268 1 : RendezvousCleanup(err);
1269 1 : }
1270 :
1271 0 : void DeviceCommissioner::OnSessionEstablished(const SessionHandle & session)
1272 : {
1273 : // PASE session established.
1274 0 : CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
1275 :
1276 : // We are in the callback for this pairing. Reset so we can pair another device.
1277 0 : mDeviceInPASEEstablishment = nullptr;
1278 :
1279 : // Make sure to clear out mRendezvousParametersForPASEEstablishment no
1280 : // matter what.
1281 0 : std::optional<RendezvousParameters> paseParameters;
1282 0 : paseParameters.swap(mRendezvousParametersForPASEEstablishment);
1283 :
1284 0 : VerifyOrReturn(device != nullptr, OnSessionEstablishmentError(CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR));
1285 :
1286 0 : CHIP_ERROR err = device->SetConnected(session);
1287 0 : if (err != CHIP_NO_ERROR)
1288 : {
1289 0 : ChipLogError(Controller, "Failed in setting up secure channel: %" CHIP_ERROR_FORMAT, err.Format());
1290 0 : OnSessionEstablishmentError(err);
1291 0 : return;
1292 : }
1293 :
1294 0 : ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake");
1295 :
1296 : MATTER_LOG_METRIC_END(kMetricDeviceCommissionerPASESession, CHIP_NO_ERROR);
1297 0 : if (mPairingDelegate != nullptr)
1298 : {
1299 : // If we started with a string payload, then at this point mPairingDelegate is
1300 : // mSetUpCodePairer, and it will provide the right SetupPayload argument to
1301 : // OnPairingComplete as needed. If mPairingDelegate is not
1302 : // mSetUpCodePairer, then we don't have a SetupPayload to provide.
1303 0 : mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR, paseParameters, std::nullopt);
1304 : }
1305 :
1306 0 : if (mRunCommissioningAfterConnection)
1307 : {
1308 0 : mRunCommissioningAfterConnection = false;
1309 : MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissionerCommission);
1310 0 : ReturnAndLogOnFailure(mDefaultCommissioner->StartCommissioning(this, device), Controller, "Failed to start commissioning");
1311 : }
1312 : }
1313 :
1314 0 : CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * device,
1315 : Credentials::CertificateType certificateType,
1316 : Optional<System::Clock::Timeout> timeout)
1317 : {
1318 : MATTER_TRACE_SCOPE("SendCertificateChainRequestCommand", "DeviceCommissioner");
1319 0 : ChipLogDetail(Controller, "Sending Certificate Chain request to %p device", device);
1320 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1321 :
1322 0 : OperationalCredentials::Commands::CertificateChainRequest::Type request;
1323 0 : request.certificateType = static_cast<OperationalCredentials::CertificateChainTypeEnum>(certificateType);
1324 0 : return SendCommissioningCommand(device, request, OnCertificateChainResponse, OnCertificateChainFailureResponse, kRootEndpointId,
1325 0 : timeout);
1326 : }
1327 :
1328 0 : void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ERROR error)
1329 : {
1330 : MATTER_TRACE_SCOPE("OnCertificateChainFailureResponse", "DeviceCommissioner");
1331 0 : ChipLogProgress(Controller, "Device failed to receive the Certificate Chain request Response: %" CHIP_ERROR_FORMAT,
1332 : error.Format());
1333 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1334 0 : commissioner->CommissioningStageComplete(error);
1335 0 : }
1336 :
1337 0 : void DeviceCommissioner::OnCertificateChainResponse(
1338 : void * context, const chip::app::Clusters::OperationalCredentials::Commands::CertificateChainResponse::DecodableType & response)
1339 : {
1340 : MATTER_TRACE_SCOPE("OnCertificateChainResponse", "DeviceCommissioner");
1341 0 : ChipLogProgress(Controller, "Received certificate chain from the device");
1342 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1343 :
1344 0 : CommissioningDelegate::CommissioningReport report;
1345 0 : report.Set<RequestedCertificate>(RequestedCertificate(response.certificate));
1346 :
1347 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1348 0 : }
1349 :
1350 0 : CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * device, const ByteSpan & attestationNonce,
1351 : Optional<System::Clock::Timeout> timeout)
1352 : {
1353 : MATTER_TRACE_SCOPE("SendAttestationRequestCommand", "DeviceCommissioner");
1354 0 : ChipLogDetail(Controller, "Sending Attestation request to %p device", device);
1355 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1356 :
1357 0 : OperationalCredentials::Commands::AttestationRequest::Type request;
1358 0 : request.attestationNonce = attestationNonce;
1359 :
1360 0 : ReturnErrorOnFailure(
1361 : SendCommissioningCommand(device, request, OnAttestationResponse, OnAttestationFailureResponse, kRootEndpointId, timeout));
1362 0 : ChipLogDetail(Controller, "Sent Attestation request, waiting for the Attestation Information");
1363 0 : return CHIP_NO_ERROR;
1364 : }
1365 :
1366 0 : void DeviceCommissioner::OnAttestationFailureResponse(void * context, CHIP_ERROR error)
1367 : {
1368 : MATTER_TRACE_SCOPE("OnAttestationFailureResponse", "DeviceCommissioner");
1369 0 : ChipLogProgress(Controller, "Device failed to receive the Attestation Information Response: %" CHIP_ERROR_FORMAT,
1370 : error.Format());
1371 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1372 0 : commissioner->CommissioningStageComplete(error);
1373 0 : }
1374 :
1375 0 : void DeviceCommissioner::OnAttestationResponse(void * context,
1376 : const OperationalCredentials::Commands::AttestationResponse::DecodableType & data)
1377 : {
1378 : MATTER_TRACE_SCOPE("OnAttestationResponse", "DeviceCommissioner");
1379 0 : ChipLogProgress(Controller, "Received Attestation Information from the device");
1380 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1381 :
1382 0 : CommissioningDelegate::CommissioningReport report;
1383 0 : report.Set<AttestationResponse>(AttestationResponse(data.attestationElements, data.attestationSignature));
1384 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1385 0 : }
1386 :
1387 0 : void DeviceCommissioner::OnDeviceAttestationInformationVerification(
1388 : void * context, const Credentials::DeviceAttestationVerifier::AttestationInfo & info, AttestationVerificationResult result)
1389 : {
1390 : MATTER_TRACE_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner");
1391 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1392 :
1393 0 : if (commissioner->mCommissioningStage == CommissioningStage::kAttestationVerification)
1394 : {
1395 : // Check for revoked DAC Chain before calling delegate. Enter next stage.
1396 :
1397 0 : CommissioningDelegate::CommissioningReport report;
1398 0 : report.Set<AttestationErrorInfo>(result);
1399 :
1400 0 : return commissioner->CommissioningStageComplete(
1401 0 : result == AttestationVerificationResult::kSuccess ? CHIP_NO_ERROR : CHIP_ERROR_FAILED_DEVICE_ATTESTATION, report);
1402 0 : }
1403 :
1404 0 : if (!commissioner->mDeviceBeingCommissioned)
1405 : {
1406 0 : ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device");
1407 0 : return;
1408 : }
1409 :
1410 0 : auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
1411 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1412 :
1413 0 : if (params.GetCompletionStatus().attestationResult.HasValue())
1414 : {
1415 0 : auto previousResult = params.GetCompletionStatus().attestationResult.Value();
1416 0 : if (previousResult != AttestationVerificationResult::kSuccess)
1417 : {
1418 0 : result = previousResult;
1419 : }
1420 : }
1421 :
1422 0 : if (result != AttestationVerificationResult::kSuccess)
1423 : {
1424 0 : CommissioningDelegate::CommissioningReport report;
1425 0 : report.Set<AttestationErrorInfo>(result);
1426 0 : if (result == AttestationVerificationResult::kNotImplemented)
1427 : {
1428 0 : ChipLogError(Controller,
1429 : "Failed in verifying 'Attestation Information' command received from the device due to default "
1430 : "DeviceAttestationVerifier Class not being overridden by a real implementation.");
1431 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_NOT_IMPLEMENTED, report);
1432 0 : return;
1433 : }
1434 :
1435 0 : ChipLogError(Controller, "Failed in verifying 'Attestation Information' command received from the device: err %hu (%s)",
1436 : static_cast<uint16_t>(result), GetAttestationResultDescription(result));
1437 : // Go look at AttestationVerificationResult enum in src/credentials/attestation_verifier/DeviceAttestationVerifier.h to
1438 : // understand the errors.
1439 :
1440 : // If a device attestation status delegate is installed, delegate handling of failure to the client and let them
1441 : // decide on whether to proceed further or not.
1442 0 : if (deviceAttestationDelegate)
1443 : {
1444 0 : commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
1445 : }
1446 : else
1447 : {
1448 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION, report);
1449 : }
1450 0 : }
1451 : else
1452 : {
1453 0 : if (deviceAttestationDelegate && deviceAttestationDelegate->ShouldWaitAfterDeviceAttestation())
1454 : {
1455 0 : commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
1456 : }
1457 : else
1458 : {
1459 0 : ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device.");
1460 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
1461 : }
1462 : }
1463 : }
1464 :
1465 0 : void DeviceCommissioner::OnArmFailSafeExtendedForDeviceAttestation(
1466 : void * context, const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType &)
1467 : {
1468 0 : ChipLogProgress(Controller, "Successfully extended fail-safe timer to handle DA failure");
1469 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1470 :
1471 : // We have completed our command invoke, but we're not going to finish the
1472 : // commissioning step until our client examines the attestation
1473 : // information. Clear out mInvokeCancelFn (which points at the
1474 : // CommandSender we just finished using) now, so it's not dangling.
1475 0 : commissioner->mInvokeCancelFn = nullptr;
1476 :
1477 0 : commissioner->HandleDeviceAttestationCompleted();
1478 0 : }
1479 :
1480 0 : void DeviceCommissioner::HandleDeviceAttestationCompleted()
1481 : {
1482 0 : if (!mDeviceBeingCommissioned)
1483 : {
1484 0 : return;
1485 : }
1486 :
1487 0 : auto & params = mDefaultCommissioner->GetCommissioningParameters();
1488 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1489 0 : if (deviceAttestationDelegate)
1490 : {
1491 0 : ChipLogProgress(Controller, "Device attestation completed, delegating continuation to client");
1492 0 : deviceAttestationDelegate->OnDeviceAttestationCompleted(this, mDeviceBeingCommissioned, *mAttestationDeviceInfo,
1493 : mAttestationResult);
1494 : }
1495 : else
1496 : {
1497 0 : ChipLogError(Controller, "Need to wait for device attestation delegate, but no delegate available. Failing commissioning");
1498 0 : CommissioningDelegate::CommissioningReport report;
1499 0 : report.Set<AttestationErrorInfo>(mAttestationResult);
1500 0 : CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1501 0 : }
1502 : }
1503 :
1504 0 : void DeviceCommissioner::OnFailedToExtendedArmFailSafeDeviceAttestation(void * context, CHIP_ERROR error)
1505 : {
1506 0 : ChipLogProgress(Controller, "Failed to extend fail-safe timer to handle attestation failure: %" CHIP_ERROR_FORMAT,
1507 : error.Format());
1508 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1509 :
1510 0 : CommissioningDelegate::CommissioningReport report;
1511 0 : report.Set<AttestationErrorInfo>(commissioner->mAttestationResult);
1512 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1513 0 : }
1514 :
1515 0 : void DeviceCommissioner::OnICDManagementRegisterClientResponse(
1516 : void * context, const app::Clusters::IcdManagement::Commands::RegisterClientResponse::DecodableType & data)
1517 : {
1518 0 : CHIP_ERROR err = CHIP_NO_ERROR;
1519 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1520 0 : VerifyOrExit(commissioner != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
1521 0 : VerifyOrExit(commissioner->mCommissioningStage == CommissioningStage::kICDRegistration, err = CHIP_ERROR_INCORRECT_STATE);
1522 0 : VerifyOrExit(commissioner->mDeviceBeingCommissioned != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
1523 :
1524 0 : if (commissioner->mPairingDelegate != nullptr)
1525 : {
1526 0 : commissioner->mPairingDelegate->OnICDRegistrationComplete(
1527 0 : ScopedNodeId(commissioner->mDeviceBeingCommissioned->GetDeviceId(), commissioner->GetFabricIndex()), data.ICDCounter);
1528 : }
1529 :
1530 0 : exit:
1531 0 : CommissioningDelegate::CommissioningReport report;
1532 0 : commissioner->CommissioningStageComplete(err, report);
1533 0 : }
1534 :
1535 0 : void DeviceCommissioner::OnICDManagementStayActiveResponse(
1536 : void * context, const app::Clusters::IcdManagement::Commands::StayActiveResponse::DecodableType & data)
1537 : {
1538 0 : CHIP_ERROR err = CHIP_NO_ERROR;
1539 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1540 0 : VerifyOrExit(commissioner != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
1541 0 : VerifyOrExit(commissioner->mCommissioningStage == CommissioningStage::kICDSendStayActive, err = CHIP_ERROR_INCORRECT_STATE);
1542 0 : VerifyOrExit(commissioner->mDeviceBeingCommissioned != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
1543 :
1544 0 : if (commissioner->mPairingDelegate != nullptr)
1545 : {
1546 0 : commissioner->mPairingDelegate->OnICDStayActiveComplete(
1547 :
1548 0 : ScopedNodeId(commissioner->mDeviceBeingCommissioned->GetDeviceId(), commissioner->GetFabricIndex()),
1549 0 : data.promisedActiveDuration);
1550 : }
1551 :
1552 0 : exit:
1553 0 : CommissioningDelegate::CommissioningReport report;
1554 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1555 0 : }
1556 :
1557 0 : bool DeviceCommissioner::ExtendArmFailSafeInternal(DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout,
1558 : Optional<System::Clock::Timeout> commandTimeout,
1559 : OnExtendFailsafeSuccess onSuccess, OnExtendFailsafeFailure onFailure,
1560 : bool fireAndForget)
1561 : {
1562 : using namespace System;
1563 : using namespace System::Clock;
1564 0 : auto now = SystemClock().GetMonotonicTimestamp();
1565 0 : auto newFailSafeTimeout = now + Seconds16(armFailSafeTimeout);
1566 0 : if (newFailSafeTimeout < proxy->GetFailSafeExpirationTimestamp())
1567 : {
1568 0 : ChipLogProgress(
1569 : Controller, "Skipping arming failsafe: new time (%u seconds from now) before old time (%u seconds from now)",
1570 : armFailSafeTimeout, std::chrono::duration_cast<Seconds16>(proxy->GetFailSafeExpirationTimestamp() - now).count());
1571 0 : return false;
1572 : }
1573 :
1574 0 : uint64_t breadcrumb = static_cast<uint64_t>(step);
1575 0 : GeneralCommissioning::Commands::ArmFailSafe::Type request;
1576 0 : request.expiryLengthSeconds = armFailSafeTimeout;
1577 0 : request.breadcrumb = breadcrumb;
1578 0 : ChipLogProgress(Controller, "Arming failsafe (%u seconds)", request.expiryLengthSeconds);
1579 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, onSuccess, onFailure, kRootEndpointId, commandTimeout, fireAndForget);
1580 0 : if (err != CHIP_NO_ERROR)
1581 : {
1582 0 : onFailure((!fireAndForget) ? this : nullptr, err);
1583 0 : return true; // we have called onFailure already
1584 : }
1585 :
1586 : // Note: The stored timestamp may become invalid if we fail asynchronously
1587 0 : proxy->SetFailSafeExpirationTimestamp(newFailSafeTimeout);
1588 0 : return true;
1589 : }
1590 :
1591 0 : void DeviceCommissioner::ExtendArmFailSafeForDeviceAttestation(const Credentials::DeviceAttestationVerifier::AttestationInfo & info,
1592 : Credentials::AttestationVerificationResult result)
1593 : {
1594 0 : mAttestationResult = result;
1595 :
1596 0 : auto & params = mDefaultCommissioner->GetCommissioningParameters();
1597 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1598 :
1599 0 : mAttestationDeviceInfo = Platform::MakeUnique<Credentials::DeviceAttestationVerifier::AttestationDeviceInfo>(info);
1600 :
1601 0 : auto expiryLengthSeconds = deviceAttestationDelegate->FailSafeExpiryTimeoutSecs();
1602 0 : bool waitForFailsafeExtension = expiryLengthSeconds.HasValue();
1603 0 : if (waitForFailsafeExtension)
1604 : {
1605 0 : ChipLogProgress(Controller, "Changing fail-safe timer to %u seconds to handle DA failure", expiryLengthSeconds.Value());
1606 : // Per spec, anything we do with the fail-safe armed must not time out
1607 : // in less than kMinimumCommissioningStepTimeout.
1608 : waitForFailsafeExtension =
1609 0 : ExtendArmFailSafeInternal(mDeviceBeingCommissioned, mCommissioningStage, expiryLengthSeconds.Value(),
1610 0 : MakeOptional(kMinimumCommissioningStepTimeout), OnArmFailSafeExtendedForDeviceAttestation,
1611 : OnFailedToExtendedArmFailSafeDeviceAttestation, /* fireAndForget = */ false);
1612 : }
1613 : else
1614 : {
1615 0 : ChipLogProgress(Controller, "Proceeding without changing fail-safe timer value as delegate has not set it");
1616 : }
1617 :
1618 0 : if (!waitForFailsafeExtension)
1619 : {
1620 0 : HandleDeviceAttestationCompleted();
1621 : }
1622 0 : }
1623 :
1624 0 : CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
1625 : {
1626 : MATTER_TRACE_SCOPE("ValidateAttestationInfo", "DeviceCommissioner");
1627 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1628 0 : VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
1629 :
1630 0 : mDeviceAttestationVerifier->VerifyAttestationInformation(info, &mDeviceAttestationInformationVerificationCallback);
1631 :
1632 : // TODO: Validate Firmware Information
1633 :
1634 0 : return CHIP_NO_ERROR;
1635 : }
1636 :
1637 : CHIP_ERROR
1638 0 : DeviceCommissioner::CheckForRevokedDACChain(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
1639 : {
1640 : MATTER_TRACE_SCOPE("CheckForRevokedDACChain", "DeviceCommissioner");
1641 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1642 0 : VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
1643 :
1644 0 : mDeviceAttestationVerifier->CheckForRevokedDACChain(info, &mDeviceAttestationInformationVerificationCallback);
1645 :
1646 0 : return CHIP_NO_ERROR;
1647 : }
1648 :
1649 0 : CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
1650 : const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce)
1651 : {
1652 : MATTER_TRACE_SCOPE("ValidateCSR", "DeviceCommissioner");
1653 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1654 0 : VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
1655 :
1656 0 : P256PublicKey dacPubkey;
1657 0 : ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
1658 :
1659 : // Retrieve attestation challenge
1660 : ByteSpan attestationChallenge =
1661 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
1662 :
1663 : // The operational CA should also verify this on its end during NOC generation, if end-to-end attestation is desired.
1664 0 : return mDeviceAttestationVerifier->VerifyNodeOperationalCSRInformation(NOCSRElements, attestationChallenge,
1665 0 : AttestationSignature, dacPubkey, csrNonce);
1666 0 : }
1667 :
1668 0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(DeviceProxy * device, const ByteSpan & csrNonce,
1669 : Optional<System::Clock::Timeout> timeout)
1670 : {
1671 : MATTER_TRACE_SCOPE("SendOperationalCertificateSigningRequestCommand", "DeviceCommissioner");
1672 0 : ChipLogDetail(Controller, "Sending CSR request to %p device", device);
1673 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1674 :
1675 0 : OperationalCredentials::Commands::CSRRequest::Type request;
1676 0 : request.CSRNonce = csrNonce;
1677 :
1678 0 : ReturnErrorOnFailure(SendCommissioningCommand(device, request, OnOperationalCertificateSigningRequest, OnCSRFailureResponse,
1679 : kRootEndpointId, timeout));
1680 0 : ChipLogDetail(Controller, "Sent CSR request, waiting for the CSR");
1681 0 : return CHIP_NO_ERROR;
1682 : }
1683 :
1684 0 : void DeviceCommissioner::OnCSRFailureResponse(void * context, CHIP_ERROR error)
1685 : {
1686 : MATTER_TRACE_SCOPE("OnCSRFailureResponse", "DeviceCommissioner");
1687 0 : ChipLogProgress(Controller, "Device failed to receive the CSR request Response: %" CHIP_ERROR_FORMAT, error.Format());
1688 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1689 0 : commissioner->CommissioningStageComplete(error);
1690 0 : }
1691 :
1692 0 : void DeviceCommissioner::OnOperationalCertificateSigningRequest(
1693 : void * context, const OperationalCredentials::Commands::CSRResponse::DecodableType & data)
1694 : {
1695 : MATTER_TRACE_SCOPE("OnOperationalCertificateSigningRequest", "DeviceCommissioner");
1696 0 : ChipLogProgress(Controller, "Received certificate signing request from the device");
1697 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1698 :
1699 0 : CommissioningDelegate::CommissioningReport report;
1700 0 : report.Set<CSRResponse>(CSRResponse(data.NOCSRElements, data.attestationSignature));
1701 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1702 0 : }
1703 :
1704 0 : void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac,
1705 : const ByteSpan & rcac, Optional<IdentityProtectionKeySpan> ipk,
1706 : Optional<NodeId> adminSubject)
1707 : {
1708 : MATTER_TRACE_SCOPE("OnDeviceNOCChainGeneration", "DeviceCommissioner");
1709 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1710 :
1711 : // The placeholder IPK is not satisfactory, but is there to fill the NocChain struct on error. It will still fail.
1712 0 : const uint8_t placeHolderIpk[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1713 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1714 0 : if (status == CHIP_NO_ERROR && !ipk.HasValue())
1715 : {
1716 0 : ChipLogError(Controller, "Did not have an IPK from the OperationalCredentialsIssuer! Cannot commission.");
1717 0 : status = CHIP_ERROR_INVALID_ARGUMENT;
1718 : }
1719 :
1720 0 : ChipLogProgress(Controller, "Received callback from the CA for NOC Chain generation. Status: %" CHIP_ERROR_FORMAT,
1721 : status.Format());
1722 0 : if (status == CHIP_NO_ERROR && commissioner->mState != State::Initialized)
1723 : {
1724 0 : status = CHIP_ERROR_INCORRECT_STATE;
1725 : }
1726 0 : if (status != CHIP_NO_ERROR)
1727 : {
1728 0 : ChipLogError(Controller, "Failed in generating device's operational credentials. Error: %" CHIP_ERROR_FORMAT,
1729 : status.Format());
1730 : }
1731 :
1732 : // TODO - Verify that the generated root cert matches with commissioner's root cert
1733 0 : CommissioningDelegate::CommissioningReport report;
1734 0 : report.Set<NocChain>(NocChain(noc, icac, rcac, ipk.HasValue() ? ipk.Value() : IdentityProtectionKeySpan(placeHolderIpk),
1735 0 : adminSubject.HasValue() ? adminSubject.Value() : commissioner->GetNodeId()));
1736 0 : commissioner->CommissioningStageComplete(status, report);
1737 0 : }
1738 :
1739 0 : CHIP_ERROR DeviceCommissioner::IssueNOCChain(const ByteSpan & NOCSRElements, NodeId nodeId,
1740 : chip::Callback::Callback<OnNOCChainGeneration> * callback)
1741 : {
1742 : MATTER_TRACE_SCOPE("IssueNOCChain", "DeviceCommissioner");
1743 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1744 :
1745 0 : ChipLogProgress(Controller, "Getting certificate chain for the device on fabric idx %u", static_cast<unsigned>(mFabricIndex));
1746 :
1747 0 : mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(nodeId);
1748 :
1749 0 : if (mFabricIndex != kUndefinedFabricIndex)
1750 : {
1751 0 : mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
1752 : }
1753 :
1754 : // Note: we don't have attestationSignature, attestationChallenge, DAC, PAI so we are just providing an empty ByteSpan
1755 : // for those arguments.
1756 0 : return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(),
1757 0 : ByteSpan(), callback);
1758 : }
1759 :
1760 0 : CHIP_ERROR DeviceCommissioner::ProcessCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
1761 : const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & pai,
1762 : const ByteSpan & csrNonce)
1763 : {
1764 : MATTER_TRACE_SCOPE("ProcessOpCSR", "DeviceCommissioner");
1765 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1766 :
1767 0 : ChipLogProgress(Controller, "Getting certificate chain for the device from the issuer");
1768 :
1769 0 : P256PublicKey dacPubkey;
1770 0 : ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
1771 :
1772 : // Retrieve attestation challenge
1773 : ByteSpan attestationChallenge =
1774 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
1775 :
1776 0 : mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(proxy->GetDeviceId());
1777 :
1778 0 : if (mFabricIndex != kUndefinedFabricIndex)
1779 : {
1780 0 : mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
1781 : }
1782 :
1783 0 : return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, csrNonce, AttestationSignature, attestationChallenge,
1784 0 : dac, pai, &mDeviceNOCChainCallback);
1785 0 : }
1786 :
1787 0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf,
1788 : const Optional<ByteSpan> & icaCertBuf,
1789 : const IdentityProtectionKeySpan ipk, const NodeId adminSubject,
1790 : Optional<System::Clock::Timeout> timeout)
1791 : {
1792 : MATTER_TRACE_SCOPE("SendOperationalCertificate", "DeviceCommissioner");
1793 :
1794 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1795 :
1796 0 : OperationalCredentials::Commands::AddNOC::Type request;
1797 0 : request.NOCValue = nocCertBuf;
1798 0 : request.ICACValue = icaCertBuf;
1799 0 : request.IPKValue = ipk;
1800 0 : request.caseAdminSubject = adminSubject;
1801 0 : request.adminVendorId = mVendorId;
1802 :
1803 0 : ReturnErrorOnFailure(SendCommissioningCommand(device, request, OnOperationalCertificateAddResponse, OnAddNOCFailureResponse,
1804 : kRootEndpointId, timeout));
1805 :
1806 0 : ChipLogProgress(Controller, "Sent operational certificate to the device");
1807 :
1808 0 : return CHIP_NO_ERROR;
1809 : }
1810 :
1811 0 : CHIP_ERROR DeviceCommissioner::ConvertFromOperationalCertStatus(OperationalCredentials::NodeOperationalCertStatusEnum err)
1812 : {
1813 : using OperationalCredentials::NodeOperationalCertStatusEnum;
1814 0 : switch (err)
1815 : {
1816 0 : case NodeOperationalCertStatusEnum::kOk:
1817 0 : return CHIP_NO_ERROR;
1818 0 : case NodeOperationalCertStatusEnum::kInvalidPublicKey:
1819 0 : return CHIP_ERROR_INVALID_PUBLIC_KEY;
1820 0 : case NodeOperationalCertStatusEnum::kInvalidNodeOpId:
1821 0 : return CHIP_ERROR_WRONG_NODE_ID;
1822 0 : case NodeOperationalCertStatusEnum::kInvalidNOC:
1823 0 : return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
1824 0 : case NodeOperationalCertStatusEnum::kMissingCsr:
1825 0 : return CHIP_ERROR_INCORRECT_STATE;
1826 0 : case NodeOperationalCertStatusEnum::kTableFull:
1827 0 : return CHIP_ERROR_NO_MEMORY;
1828 0 : case NodeOperationalCertStatusEnum::kInvalidAdminSubject:
1829 0 : return CHIP_ERROR_INVALID_ADMIN_SUBJECT;
1830 0 : case NodeOperationalCertStatusEnum::kFabricConflict:
1831 0 : return CHIP_ERROR_FABRIC_EXISTS;
1832 0 : case NodeOperationalCertStatusEnum::kLabelConflict:
1833 0 : return CHIP_ERROR_INVALID_ARGUMENT;
1834 0 : case NodeOperationalCertStatusEnum::kInvalidFabricIndex:
1835 0 : return CHIP_ERROR_INVALID_FABRIC_INDEX;
1836 0 : case NodeOperationalCertStatusEnum::kUnknownEnumValue:
1837 : // Is this a reasonable value?
1838 0 : return CHIP_ERROR_CERT_LOAD_FAILED;
1839 : }
1840 :
1841 0 : return CHIP_ERROR_CERT_LOAD_FAILED;
1842 : }
1843 :
1844 0 : void DeviceCommissioner::OnAddNOCFailureResponse(void * context, CHIP_ERROR error)
1845 : {
1846 : MATTER_TRACE_SCOPE("OnAddNOCFailureResponse", "DeviceCommissioner");
1847 0 : ChipLogProgress(Controller, "Device failed to receive the operational certificate Response: %" CHIP_ERROR_FORMAT,
1848 : error.Format());
1849 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1850 0 : commissioner->CommissioningStageComplete(error);
1851 0 : }
1852 :
1853 0 : void DeviceCommissioner::OnOperationalCertificateAddResponse(
1854 : void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data)
1855 : {
1856 : MATTER_TRACE_SCOPE("OnOperationalCertificateAddResponse", "DeviceCommissioner");
1857 0 : ChipLogProgress(Controller, "Device returned status %d on receiving the NOC", to_underlying(data.statusCode));
1858 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1859 :
1860 0 : CHIP_ERROR err = CHIP_NO_ERROR;
1861 :
1862 0 : VerifyOrExit(commissioner->mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
1863 :
1864 0 : VerifyOrExit(commissioner->mDeviceBeingCommissioned != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
1865 :
1866 0 : err = ConvertFromOperationalCertStatus(data.statusCode);
1867 0 : SuccessOrExit(err);
1868 :
1869 0 : err = commissioner->OnOperationalCredentialsProvisioningCompletion(commissioner->mDeviceBeingCommissioned);
1870 :
1871 0 : exit:
1872 0 : if (err != CHIP_NO_ERROR)
1873 : {
1874 0 : ChipLogProgress(Controller, "Add NOC failed with error: %" CHIP_ERROR_FORMAT, err.Format());
1875 0 : commissioner->CommissioningStageComplete(err);
1876 : }
1877 0 : }
1878 :
1879 0 : CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, const ByteSpan & rcac,
1880 : Optional<System::Clock::Timeout> timeout)
1881 : {
1882 : MATTER_TRACE_SCOPE("SendTrustedRootCertificate", "DeviceCommissioner");
1883 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1884 :
1885 0 : ChipLogProgress(Controller, "Sending root certificate to the device");
1886 :
1887 0 : OperationalCredentials::Commands::AddTrustedRootCertificate::Type request;
1888 0 : request.rootCACertificate = rcac;
1889 0 : ReturnErrorOnFailure(
1890 : SendCommissioningCommand(device, request, OnRootCertSuccessResponse, OnRootCertFailureResponse, kRootEndpointId, timeout));
1891 :
1892 0 : ChipLogProgress(Controller, "Sent root certificate to the device");
1893 :
1894 0 : return CHIP_NO_ERROR;
1895 : }
1896 :
1897 0 : void DeviceCommissioner::OnRootCertSuccessResponse(void * context, const chip::app::DataModel::NullObjectType &)
1898 : {
1899 : MATTER_TRACE_SCOPE("OnRootCertSuccessResponse", "DeviceCommissioner");
1900 0 : ChipLogProgress(Controller, "Device confirmed that it has received the root certificate");
1901 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1902 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
1903 0 : }
1904 :
1905 0 : void DeviceCommissioner::OnRootCertFailureResponse(void * context, CHIP_ERROR error)
1906 : {
1907 : MATTER_TRACE_SCOPE("OnRootCertFailureResponse", "DeviceCommissioner");
1908 0 : ChipLogProgress(Controller, "Device failed to receive the root certificate Response: %" CHIP_ERROR_FORMAT, error.Format());
1909 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1910 0 : commissioner->CommissioningStageComplete(error);
1911 0 : }
1912 :
1913 0 : CHIP_ERROR DeviceCommissioner::OnOperationalCredentialsProvisioningCompletion(DeviceProxy * device)
1914 : {
1915 : MATTER_TRACE_SCOPE("OnOperationalCredentialsProvisioningCompletion", "DeviceCommissioner");
1916 0 : ChipLogProgress(Controller, "Operational credentials provisioned on device %p", device);
1917 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1918 :
1919 0 : if (mPairingDelegate != nullptr)
1920 : {
1921 0 : mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingSuccess);
1922 : }
1923 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1924 :
1925 0 : return CHIP_NO_ERROR;
1926 : }
1927 :
1928 : #if CONFIG_NETWORK_LAYER_BLE
1929 : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1930 : void DeviceCommissioner::ConnectBleTransportToSelf()
1931 : {
1932 : Transport::BLEBase & transport = std::get<Transport::BLE<1>>(mSystemState->TransportMgr()->GetTransport().GetTransports());
1933 : if (!transport.IsBleLayerTransportSetToSelf())
1934 : {
1935 : transport.SetBleLayerTransportToSelf();
1936 : }
1937 : }
1938 : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1939 :
1940 0 : void DeviceCommissioner::CloseBleConnection()
1941 : {
1942 : // It is fine since we can only commission one device at the same time.
1943 : // We should be able to distinguish different BLE connections if we want
1944 : // to commission multiple devices at the same time over BLE.
1945 0 : mSystemState->BleLayer()->CloseAllBleConnections();
1946 0 : }
1947 : #endif
1948 :
1949 0 : CHIP_ERROR DeviceCommissioner::DiscoverCommissionableNodes(Dnssd::DiscoveryFilter filter)
1950 : {
1951 0 : ReturnErrorOnFailure(SetUpNodeDiscovery());
1952 0 : return mDNSResolver.DiscoverCommissionableNodes(filter);
1953 : }
1954 :
1955 2 : CHIP_ERROR DeviceCommissioner::StopCommissionableDiscovery()
1956 : {
1957 2 : return mDNSResolver.StopDiscovery();
1958 : }
1959 :
1960 0 : const Dnssd::CommissionNodeData * DeviceCommissioner::GetDiscoveredDevice(int idx)
1961 : {
1962 0 : return GetDiscoveredNode(idx);
1963 : }
1964 :
1965 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
1966 :
1967 : CHIP_ERROR DeviceCommissioner::SetUdcListenPort(uint16_t listenPort)
1968 : {
1969 : if (mState == State::Initialized)
1970 : {
1971 : return CHIP_ERROR_INCORRECT_STATE;
1972 : }
1973 :
1974 : mUdcListenPort = listenPort;
1975 : return CHIP_NO_ERROR;
1976 : }
1977 :
1978 : void DeviceCommissioner::FindCommissionableNode(const char * instanceName)
1979 : {
1980 : Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kInstanceName, instanceName);
1981 : TEMPORARY_RETURN_IGNORED DiscoverCommissionableNodes(filter);
1982 : }
1983 :
1984 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1985 :
1986 0 : void DeviceCommissioner::OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData)
1987 : {
1988 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1989 : if (mUdcServer != nullptr)
1990 : {
1991 : mUdcServer->OnCommissionableNodeFound(nodeData);
1992 : }
1993 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1994 0 : if (nodeData.Get<Dnssd::CommissionNodeData>().threadMeshcop)
1995 : {
1996 0 : mAutoCommissioner.SetNetworkSetupNeeded(true);
1997 : }
1998 0 : AbstractDnssdDiscoveryController::OnNodeDiscovered(nodeData);
1999 0 : mSetUpCodePairer.NotifyCommissionableDeviceDiscovered(nodeData);
2000 0 : }
2001 :
2002 0 : void DeviceCommissioner::OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &)
2003 : {
2004 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2005 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
2006 0 : }
2007 :
2008 0 : void DeviceCommissioner::OnBasicFailure(void * context, CHIP_ERROR error)
2009 : {
2010 0 : ChipLogProgress(Controller, "Received failure response: %" CHIP_ERROR_FORMAT, error.Format());
2011 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2012 0 : commissioner->CommissioningStageComplete(error);
2013 0 : }
2014 :
2015 0 : static GeneralCommissioning::Commands::ArmFailSafe::Type DisarmFailsafeRequest()
2016 : {
2017 0 : GeneralCommissioning::Commands::ArmFailSafe::Type request;
2018 0 : request.expiryLengthSeconds = 0; // Expire immediately.
2019 0 : request.breadcrumb = 0;
2020 0 : return request;
2021 : }
2022 :
2023 0 : static void MarkForEviction(const Optional<SessionHandle> & session)
2024 : {
2025 0 : if (session.HasValue())
2026 : {
2027 0 : session.Value()->AsSecureSession()->MarkForEviction();
2028 : }
2029 0 : }
2030 :
2031 0 : void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
2032 : {
2033 : // At this point, proxy == mDeviceBeingCommissioned, nodeId == mDeviceBeingCommissioned->GetDeviceId()
2034 :
2035 0 : mCommissioningCompletionStatus = completionStatus;
2036 :
2037 0 : if (completionStatus.err == CHIP_NO_ERROR)
2038 : {
2039 : // CommissioningStageComplete uses mDeviceBeingCommissioned, which can
2040 : // be commissionee if we are cleaning up before we've gone operational. Normally
2041 : // that would not happen in this non-error case, _except_ if we were told to skip sending
2042 : // CommissioningComplete: in that case we do not have an operational DeviceProxy, so
2043 : // we're using our CommissioneeDeviceProxy to do a successful cleanup.
2044 : //
2045 : // This means we have to call CommissioningStageComplete() before we destroy commissionee.
2046 : //
2047 : // This should be safe, because CommissioningStageComplete() does not call CleanupCommissioning
2048 : // when called in the cleanup stage (which is where we are), and StopPairing does not directly release
2049 : // mDeviceBeingCommissioned.
2050 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2051 :
2052 0 : CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
2053 0 : if (commissionee != nullptr)
2054 : {
2055 0 : ReleaseCommissioneeDevice(commissionee);
2056 : }
2057 : // Send the callbacks, we're done.
2058 0 : SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
2059 : }
2060 0 : else if (completionStatus.err == CHIP_ERROR_CANCELLED)
2061 : {
2062 : // If we're cleaning up because cancellation has been requested via StopPairing(), expire the failsafe
2063 : // in the background and reset our state synchronously, so a new commissioning attempt can be started.
2064 0 : CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
2065 0 : SessionHolder session((commissionee == proxy) ? commissionee->DetachSecureSession().Value()
2066 0 : : proxy->GetSecureSession().Value());
2067 :
2068 0 : auto request = DisarmFailsafeRequest();
2069 0 : auto onSuccessCb = [session](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus,
2070 : const decltype(request)::ResponseType & responseData) {
2071 0 : ChipLogProgress(Controller, "Failsafe disarmed");
2072 0 : MarkForEviction(session.Get());
2073 0 : };
2074 0 : auto onFailureCb = [session](CHIP_ERROR aError) {
2075 0 : ChipLogProgress(Controller, "Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, aError.Format());
2076 0 : MarkForEviction(session.Get());
2077 0 : };
2078 :
2079 0 : ChipLogProgress(Controller, "Disarming failsafe on device %p in background", proxy);
2080 0 : CHIP_ERROR err = InvokeCommandRequest(proxy->GetExchangeManager(), session.Get().Value(), kRootEndpointId, request,
2081 : onSuccessCb, onFailureCb);
2082 0 : if (err != CHIP_NO_ERROR)
2083 : {
2084 0 : ChipLogError(Controller, "Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format());
2085 : }
2086 :
2087 0 : CleanupDoneAfterError();
2088 0 : }
2089 0 : else if (completionStatus.failedStage.HasValue() && completionStatus.failedStage.Value() >= kWiFiNetworkSetup)
2090 : {
2091 : // If we were already doing network setup, we need to retain the pase session and start again from network setup stage.
2092 : // We do not need to reset the failsafe here because we want to keep everything on the device up to this point, so just
2093 : // send the completion callbacks (see "Commissioning Flows Error Handling" in the spec).
2094 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2095 0 : SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
2096 : }
2097 : else
2098 : {
2099 : // If we've failed somewhere in the early stages (or we don't have a failedStage specified), we need to start from the
2100 : // beginning. However, because some of the commands can only be sent once per arm-failsafe, we also need to force a reset on
2101 : // the failsafe so we can start fresh on the next attempt.
2102 0 : ChipLogProgress(Controller, "Disarming failsafe on device %p", proxy);
2103 0 : auto request = DisarmFailsafeRequest();
2104 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure, kRootEndpointId);
2105 0 : if (err != CHIP_NO_ERROR)
2106 : {
2107 : // We won't get any async callbacks here, so just pretend like the command errored out async.
2108 0 : ChipLogError(Controller, "Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format());
2109 0 : CleanupDoneAfterError();
2110 : }
2111 : }
2112 0 : }
2113 :
2114 0 : void DeviceCommissioner::OnDisarmFailsafe(void * context,
2115 : const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
2116 : {
2117 0 : ChipLogProgress(Controller, "Failsafe disarmed");
2118 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2119 0 : commissioner->CleanupDoneAfterError();
2120 0 : }
2121 :
2122 0 : void DeviceCommissioner::OnDisarmFailsafeFailure(void * context, CHIP_ERROR error)
2123 : {
2124 0 : ChipLogProgress(Controller, "Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, error.Format());
2125 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2126 0 : commissioner->CleanupDoneAfterError();
2127 0 : }
2128 :
2129 0 : void DeviceCommissioner::CleanupDoneAfterError()
2130 : {
2131 : // If someone nulled out our mDeviceBeingCommissioned, there's nothing else
2132 : // to do here.
2133 0 : VerifyOrReturn(mDeviceBeingCommissioned != nullptr);
2134 :
2135 0 : NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId();
2136 :
2137 : // Signal completion - this will reset mDeviceBeingCommissioned.
2138 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2139 :
2140 : // At this point, we also want to close off the pase session so we need to re-establish
2141 0 : CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
2142 :
2143 : // If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection.
2144 0 : if (commissionee != nullptr)
2145 : {
2146 0 : ReleaseCommissioneeDevice(commissionee);
2147 : }
2148 :
2149 : // Invoke callbacks last, after we have cleared up all state.
2150 0 : SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus);
2151 : }
2152 :
2153 0 : void DeviceCommissioner::SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus)
2154 : {
2155 : MATTER_LOG_METRIC_END(kMetricDeviceCommissionerCommission, completionStatus.err);
2156 :
2157 0 : ChipLogProgress(Controller, "Commissioning complete for node ID 0x" ChipLogFormatX64 ": %s", ChipLogValueX64(nodeId),
2158 : (completionStatus.err == CHIP_NO_ERROR ? "success" : completionStatus.err.AsString()));
2159 0 : mCommissioningStage = CommissioningStage::kSecurePairing;
2160 :
2161 0 : if (mPairingDelegate == nullptr)
2162 : {
2163 0 : return;
2164 : }
2165 :
2166 0 : mPairingDelegate->OnCommissioningComplete(nodeId, completionStatus.err);
2167 :
2168 0 : PeerId peerId(GetCompressedFabricId(), nodeId);
2169 0 : if (completionStatus.err == CHIP_NO_ERROR)
2170 : {
2171 0 : mPairingDelegate->OnCommissioningSuccess(peerId);
2172 : }
2173 : else
2174 : {
2175 : // TODO: We should propogate detailed error information (commissioningError, networkCommissioningStatus) from
2176 : // completionStatus.
2177 0 : mPairingDelegate->OnCommissioningFailure(peerId, completionStatus.err, completionStatus.failedStage.ValueOr(kError),
2178 0 : completionStatus.attestationResult);
2179 : }
2180 : }
2181 :
2182 0 : void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report)
2183 : {
2184 : // Once this stage is complete, reset mDeviceBeingCommissioned - this will be reset when the delegate calls the next step.
2185 : MATTER_TRACE_SCOPE("CommissioningStageComplete", "DeviceCommissioner");
2186 : MATTER_LOG_METRIC_END(MetricKeyForCommissioningStage(mCommissioningStage), err);
2187 0 : VerifyOrDie(mDeviceBeingCommissioned);
2188 :
2189 0 : NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId();
2190 0 : DeviceProxy * proxy = mDeviceBeingCommissioned;
2191 0 : mDeviceBeingCommissioned = nullptr;
2192 0 : mInvokeCancelFn = nullptr;
2193 0 : mWriteCancelFn = nullptr;
2194 :
2195 0 : if (mPairingDelegate != nullptr)
2196 : {
2197 0 : mPairingDelegate->OnCommissioningStatusUpdate(PeerId(GetCompressedFabricId(), nodeId), mCommissioningStage, err);
2198 : }
2199 :
2200 0 : if (mCommissioningDelegate == nullptr)
2201 : {
2202 0 : return;
2203 : }
2204 0 : report.stageCompleted = mCommissioningStage;
2205 0 : CHIP_ERROR status = mCommissioningDelegate->CommissioningStepFinished(err, report);
2206 0 : if (status != CHIP_NO_ERROR && mCommissioningStage != CommissioningStage::kCleanup)
2207 : {
2208 : // Commissioning delegate will only return error if it failed to perform the appropriate commissioning step.
2209 : // In this case, we should complete the commissioning for it.
2210 0 : CompletionStatus completionStatus;
2211 0 : completionStatus.err = status;
2212 0 : completionStatus.failedStage = MakeOptional(report.stageCompleted);
2213 0 : mCommissioningStage = CommissioningStage::kCleanup;
2214 0 : mDeviceBeingCommissioned = proxy;
2215 0 : CleanupCommissioning(proxy, nodeId, completionStatus);
2216 : }
2217 : }
2218 :
2219 0 : void DeviceCommissioner::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
2220 : const SessionHandle & sessionHandle)
2221 : {
2222 : // CASE session established.
2223 : MATTER_LOG_METRIC_END(kMetricDeviceCommissioningOperationalSetup, CHIP_NO_ERROR);
2224 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2225 0 : VerifyOrDie(commissioner->mCommissioningStage == CommissioningStage::kFindOperationalForStayActive ||
2226 : commissioner->mCommissioningStage == CommissioningStage::kFindOperationalForCommissioningComplete);
2227 0 : VerifyOrDie(commissioner->mDeviceBeingCommissioned->GetDeviceId() == sessionHandle->GetPeer().GetNodeId());
2228 0 : commissioner->CancelCASECallbacks(); // ensure all CASE callbacks are unregistered
2229 :
2230 0 : CommissioningDelegate::CommissioningReport report;
2231 0 : report.Set<OperationalNodeFoundData>(OperationalNodeFoundData(OperationalDeviceProxy(&exchangeMgr, sessionHandle)));
2232 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
2233 0 : }
2234 :
2235 0 : void DeviceCommissioner::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
2236 : {
2237 : // CASE session establishment failed.
2238 : MATTER_LOG_METRIC_END(kMetricDeviceCommissioningOperationalSetup, error);
2239 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2240 0 : VerifyOrDie(commissioner->mCommissioningStage == CommissioningStage::kFindOperationalForStayActive ||
2241 : commissioner->mCommissioningStage == CommissioningStage::kFindOperationalForCommissioningComplete);
2242 0 : VerifyOrDie(commissioner->mDeviceBeingCommissioned->GetDeviceId() == peerId.GetNodeId());
2243 0 : commissioner->CancelCASECallbacks(); // ensure all CASE callbacks are unregistered
2244 :
2245 0 : if (error != CHIP_NO_ERROR)
2246 : {
2247 0 : ChipLogProgress(Controller, "Device connection failed. Error %" CHIP_ERROR_FORMAT, error.Format());
2248 : }
2249 : else
2250 : {
2251 : // Ensure that commissioning stage advancement is done based on seeing an error.
2252 0 : ChipLogError(Controller, "Device connection failed without a valid error code.");
2253 0 : error = CHIP_ERROR_INTERNAL;
2254 : }
2255 0 : commissioner->CommissioningStageComplete(error);
2256 0 : }
2257 :
2258 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
2259 : // No specific action to take on either success or failure here; we're just
2260 : // trying to bump the fail-safe, and if that fails it's not clear there's much
2261 : // we can to with that.
2262 0 : static void OnExtendFailsafeForCASERetryFailure(void * context, CHIP_ERROR error)
2263 : {
2264 0 : ChipLogError(Controller, "Failed to extend fail-safe for CASE retry: %" CHIP_ERROR_FORMAT, error.Format());
2265 0 : }
2266 : static void
2267 0 : OnExtendFailsafeForCASERetrySuccess(void * context,
2268 : const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
2269 : {
2270 0 : ChipLogProgress(Controller, "Status of extending fail-safe for CASE retry: %u", to_underlying(data.errorCode));
2271 0 : }
2272 :
2273 0 : void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error,
2274 : System::Clock::Seconds16 retryTimeout)
2275 : {
2276 0 : ChipLogError(Controller,
2277 : "Session establishment failed for " ChipLogFormatScopedNodeId ", error: %" CHIP_ERROR_FORMAT
2278 : ". Next retry expected to get a response to Sigma1 or fail within %d seconds",
2279 : ChipLogValueScopedNodeId(peerId), error.Format(), retryTimeout.count());
2280 :
2281 0 : auto self = static_cast<DeviceCommissioner *>(context);
2282 0 : VerifyOrDie(self->GetCommissioningStage() == CommissioningStage::kFindOperationalForStayActive ||
2283 : self->GetCommissioningStage() == CommissioningStage::kFindOperationalForCommissioningComplete);
2284 0 : VerifyOrDie(self->mDeviceBeingCommissioned->GetDeviceId() == peerId.GetNodeId());
2285 :
2286 : bool supportsConcurrent =
2287 0 : self->mCommissioningDelegate->GetCommissioningParameters().GetSupportsConcurrentConnection().ValueOr(true);
2288 0 : if (!supportsConcurrent)
2289 : {
2290 : // Concurrent mode not supported.
2291 : // We are in operational phase so the commissioning channel is not
2292 : // available anymore and it is not possible to re-arm the fail-safe timer.
2293 0 : return;
2294 : }
2295 :
2296 : // We need to do the fail-safe arming over the PASE session.
2297 0 : auto * commissioneeDevice = self->FindCommissioneeDevice(peerId.GetNodeId());
2298 0 : if (!commissioneeDevice)
2299 : {
2300 : // Commissioning canceled, presumably. Just ignore the notification,
2301 : // not much we can do here.
2302 0 : return;
2303 : }
2304 :
2305 : // Extend by the default failsafe timeout plus our retry timeout, so we can
2306 : // be sure the fail-safe will not expire before we try the next time, if
2307 : // there will be a next time.
2308 : //
2309 : // TODO: Make it possible for our clients to control the exact timeout here?
2310 : uint16_t failsafeTimeout;
2311 0 : if (UINT16_MAX - retryTimeout.count() < kDefaultFailsafeTimeout)
2312 : {
2313 0 : failsafeTimeout = UINT16_MAX;
2314 : }
2315 : else
2316 : {
2317 0 : failsafeTimeout = static_cast<uint16_t>(retryTimeout.count() + kDefaultFailsafeTimeout);
2318 : }
2319 :
2320 : // A false return is fine; we don't want to make the fail-safe shorter here.
2321 0 : self->ExtendArmFailSafeInternal(commissioneeDevice, self->GetCommissioningStage(), failsafeTimeout,
2322 0 : MakeOptional(kMinimumCommissioningStepTimeout), OnExtendFailsafeForCASERetrySuccess,
2323 : OnExtendFailsafeForCASERetryFailure, /* fireAndForget = */ true);
2324 : }
2325 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
2326 :
2327 : // ClusterStateCache::Callback / ReadClient::Callback
2328 0 : void DeviceCommissioner::OnDone(app::ReadClient * readClient)
2329 : {
2330 0 : VerifyOrDie(readClient != nullptr && readClient == mReadClient.get());
2331 0 : mReadClient.reset();
2332 0 : switch (mCommissioningStage)
2333 : {
2334 0 : case CommissioningStage::kReadCommissioningInfo:
2335 0 : ContinueReadingCommissioningInfo(mCommissioningDelegate->GetCommissioningParameters());
2336 0 : break;
2337 0 : default:
2338 0 : VerifyOrDie(false);
2339 : break;
2340 : }
2341 0 : }
2342 :
2343 : namespace {
2344 : // Helper for grouping attribute paths into read interactions in ContinueReadingCommissioningInfo()
2345 : // below. The logic generates a sequence of calls to AddAttributePath(), stopping when the capacity
2346 : // of the builder is exceeded. When creating subsequent read requests, the same sequence of calls
2347 : // is generated again, but the builder will skip however many attributes were already read in
2348 : // previous requests. This makes it easy to have logic that conditionally reads attributes, without
2349 : // needing to write manual code to work out where subsequent reads need to resume -- the logic that
2350 : // decides which attributes to read simply needs to be repeatable / deterministic.
2351 : class ReadInteractionBuilder
2352 : {
2353 : static constexpr auto kCapacity = InteractionModelEngine::kMinSupportedPathsPerReadRequest;
2354 :
2355 : size_t mSkip = 0;
2356 : size_t mCount = 0;
2357 : app::AttributePathParams mPaths[kCapacity];
2358 :
2359 : public:
2360 0 : ReadInteractionBuilder(size_t skip = 0) : mSkip(skip) {}
2361 :
2362 0 : size_t size() { return std::min(mCount, kCapacity); }
2363 0 : bool exceeded() { return mCount > kCapacity; }
2364 0 : app::AttributePathParams * paths() { return mPaths; }
2365 :
2366 : // Adds an attribute path if within the current window.
2367 : // Returns false if the available space has been exceeded.
2368 : template <typename... Ts>
2369 0 : bool AddAttributePath(Ts &&... args)
2370 : {
2371 0 : if (mSkip > 0)
2372 : {
2373 0 : mSkip--;
2374 0 : return true;
2375 : }
2376 0 : if (mCount >= kCapacity)
2377 : {
2378 : // capacity exceeded
2379 0 : mCount = kCapacity + 1;
2380 0 : return false;
2381 : }
2382 0 : mPaths[mCount++] = app::AttributePathParams(std::forward<Ts>(args)...);
2383 0 : return true;
2384 : }
2385 : };
2386 : } // namespace
2387 :
2388 0 : void DeviceCommissioner::ContinueReadingCommissioningInfo(const CommissioningParameters & params)
2389 : {
2390 0 : VerifyOrDie(mCommissioningStage == CommissioningStage::kReadCommissioningInfo);
2391 :
2392 : // mReadCommissioningInfoProgress starts at 0 and counts the number of paths we have read.
2393 : // A marker value is used to indicate that there are no further attributes to read.
2394 : static constexpr auto kReadProgressNoFurtherAttributes = std::numeric_limits<decltype(mReadCommissioningInfoProgress)>::max();
2395 0 : if (mReadCommissioningInfoProgress == kReadProgressNoFurtherAttributes)
2396 : {
2397 0 : FinishReadingCommissioningInfo(params);
2398 0 : return;
2399 : }
2400 :
2401 : // We can ony read 9 paths per Read Interaction, since that is the minimum a server has to
2402 : // support per spec (see "Interaction Model Limits"), so we generally need to perform more
2403 : // that one interaction. To build the list of attributes for each interaction, we use a
2404 : // builder that skips adding paths that we already handled in a previous interaction, and
2405 : // returns false if the current request is exhausted. This construction avoids allocating
2406 : // memory to hold the complete list of attributes to read up front; however the logic to
2407 : // determine the attributes to include must be deterministic since it runs multiple times.
2408 : // The use of an immediately-invoked lambda is convenient for control flow.
2409 0 : ReadInteractionBuilder builder(mReadCommissioningInfoProgress);
2410 0 : [&]() -> void {
2411 : // General Commissioning
2412 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2413 : Clusters::GeneralCommissioning::Attributes::SupportsConcurrentConnection::Id));
2414 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2415 : Clusters::GeneralCommissioning::Attributes::Breadcrumb::Id));
2416 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2417 : Clusters::GeneralCommissioning::Attributes::BasicCommissioningInfo::Id));
2418 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2419 : Clusters::GeneralCommissioning::Attributes::RegulatoryConfig::Id));
2420 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2421 : Clusters::GeneralCommissioning::Attributes::LocationCapability::Id));
2422 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::GeneralCommissioning::Id,
2423 : Clusters::GeneralCommissioning::Attributes::IsCommissioningWithoutPower::Id));
2424 :
2425 : // Basic Information: VID and PID for device attestation purposes
2426 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::BasicInformation::Id,
2427 : Clusters::BasicInformation::Attributes::VendorID::Id));
2428 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::BasicInformation::Id,
2429 : Clusters::BasicInformation::Attributes::ProductID::Id));
2430 :
2431 : // Time Synchronization: all attributes
2432 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::TimeSynchronization::Id));
2433 :
2434 : // Network Commissioning (all endpoints): Read the feature map and connect time
2435 : // TODO: Expose a flag that disables network setup so we don't need to read this
2436 0 : VerifyOrReturn(builder.AddAttributePath(Clusters::NetworkCommissioning::Id,
2437 : Clusters::NetworkCommissioning::Attributes::FeatureMap::Id));
2438 0 : VerifyOrReturn(builder.AddAttributePath(Clusters::NetworkCommissioning::Id,
2439 : Clusters::NetworkCommissioning::Attributes::ConnectMaxTimeSeconds::Id));
2440 :
2441 : // If we were asked to do network scans, also read ScanMaxTimeSeconds,
2442 : // so we know how long to wait for those.
2443 0 : if (params.GetAttemptWiFiNetworkScan().ValueOr(false) || params.GetAttemptThreadNetworkScan().ValueOr(false))
2444 : {
2445 0 : VerifyOrReturn(builder.AddAttributePath(Clusters::NetworkCommissioning::Id,
2446 : Clusters::NetworkCommissioning::Attributes::ScanMaxTimeSeconds::Id));
2447 : }
2448 :
2449 : // OperationalCredentials: existing fabrics, if necessary
2450 0 : if (params.GetCheckForMatchingFabric())
2451 : {
2452 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::OperationalCredentials::Id,
2453 : Clusters::OperationalCredentials::Attributes::Fabrics::Id));
2454 : }
2455 :
2456 : // ICD Management
2457 0 : if (params.GetICDRegistrationStrategy() != ICDRegistrationStrategy::kIgnore)
2458 : {
2459 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2460 : Clusters::IcdManagement::Attributes::FeatureMap::Id));
2461 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2462 : Clusters::IcdManagement::Attributes::UserActiveModeTriggerHint::Id));
2463 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2464 : Clusters::IcdManagement::Attributes::UserActiveModeTriggerInstruction::Id));
2465 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2466 : Clusters::IcdManagement::Attributes::IdleModeDuration::Id));
2467 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2468 : Clusters::IcdManagement::Attributes::ActiveModeDuration::Id));
2469 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2470 : Clusters::IcdManagement::Attributes::ActiveModeThreshold::Id));
2471 0 : VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
2472 : Clusters::IcdManagement::Attributes::ClusterRevision::Id));
2473 : }
2474 :
2475 : // Extra paths requested via CommissioningParameters
2476 0 : for (auto const & path : params.GetExtraReadPaths())
2477 : {
2478 0 : VerifyOrReturn(builder.AddAttributePath(path));
2479 : }
2480 0 : }();
2481 :
2482 0 : VerifyOrDie(builder.size() > 0); // our logic is broken if there is nothing to read
2483 0 : if (builder.exceeded())
2484 : {
2485 : // Keep track of the number of attributes we have read already so we can resume from there.
2486 0 : auto progress = mReadCommissioningInfoProgress + builder.size();
2487 0 : VerifyOrDie(progress < kReadProgressNoFurtherAttributes);
2488 0 : mReadCommissioningInfoProgress = static_cast<decltype(mReadCommissioningInfoProgress)>(progress);
2489 : }
2490 : else
2491 : {
2492 0 : mReadCommissioningInfoProgress = kReadProgressNoFurtherAttributes;
2493 : }
2494 :
2495 0 : SendCommissioningReadRequest(mDeviceBeingCommissioned, mCommissioningStepTimeout, builder.paths(), builder.size());
2496 : }
2497 :
2498 : namespace {
2499 0 : void AccumulateErrors(CHIP_ERROR & acc, CHIP_ERROR err)
2500 : {
2501 0 : if (acc == CHIP_NO_ERROR && err != CHIP_NO_ERROR)
2502 : {
2503 0 : acc = err;
2504 : }
2505 0 : }
2506 : } // namespace
2507 :
2508 0 : void DeviceCommissioner::FinishReadingCommissioningInfo(const CommissioningParameters & params)
2509 : {
2510 : // We want to parse as much information as possible, even if we eventually end
2511 : // up returning an error (e.g. because some mandatory information was missing).
2512 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2513 0 : ReadCommissioningInfo info;
2514 0 : info.attributes = mAttributeCache.get();
2515 0 : AccumulateErrors(err, ParseGeneralCommissioningInfo(info));
2516 0 : AccumulateErrors(err, ParseBasicInformation(info));
2517 0 : AccumulateErrors(err, ParseNetworkCommissioningInfo(info));
2518 0 : AccumulateErrors(err, ParseTimeSyncInfo(info));
2519 0 : AccumulateErrors(err, ParseFabrics(info));
2520 0 : AccumulateErrors(err, ParseICDInfo(info));
2521 0 : AccumulateErrors(err, ParseExtraCommissioningInfo(info, params));
2522 :
2523 0 : if (mPairingDelegate != nullptr && err == CHIP_NO_ERROR)
2524 : {
2525 0 : mPairingDelegate->OnReadCommissioningInfo(info);
2526 : }
2527 :
2528 0 : CommissioningDelegate::CommissioningReport report;
2529 0 : report.Set<ReadCommissioningInfo>(info);
2530 0 : CommissioningStageComplete(err, report);
2531 :
2532 : // Only release the attribute cache once `info` is no longer needed.
2533 0 : mAttributeCache.reset();
2534 0 : }
2535 :
2536 0 : CHIP_ERROR DeviceCommissioner::ParseGeneralCommissioningInfo(ReadCommissioningInfo & info)
2537 : {
2538 : using namespace GeneralCommissioning::Attributes;
2539 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
2540 : CHIP_ERROR err;
2541 :
2542 0 : BasicCommissioningInfo::TypeInfo::DecodableType basicInfo;
2543 0 : err = mAttributeCache->Get<BasicCommissioningInfo::TypeInfo>(kRootEndpointId, basicInfo);
2544 0 : if (err == CHIP_NO_ERROR)
2545 : {
2546 0 : info.general.recommendedFailsafe = basicInfo.failSafeExpiryLengthSeconds;
2547 : }
2548 : else
2549 : {
2550 0 : ChipLogError(Controller, "Failed to read BasicCommissioningInfo: %" CHIP_ERROR_FORMAT, err.Format());
2551 0 : return_err = err;
2552 : }
2553 :
2554 0 : err = mAttributeCache->Get<RegulatoryConfig::TypeInfo>(kRootEndpointId, info.general.currentRegulatoryLocation);
2555 0 : if (err != CHIP_NO_ERROR)
2556 : {
2557 0 : ChipLogError(Controller, "Failed to read RegulatoryConfig: %" CHIP_ERROR_FORMAT, err.Format());
2558 0 : return_err = err;
2559 : }
2560 :
2561 0 : err = mAttributeCache->Get<LocationCapability::TypeInfo>(kRootEndpointId, info.general.locationCapability);
2562 0 : if (err != CHIP_NO_ERROR)
2563 : {
2564 0 : ChipLogError(Controller, "Failed to read LocationCapability: %" CHIP_ERROR_FORMAT, err.Format());
2565 0 : return_err = err;
2566 : }
2567 :
2568 0 : err = mAttributeCache->Get<Breadcrumb::TypeInfo>(kRootEndpointId, info.general.breadcrumb);
2569 0 : if (err != CHIP_NO_ERROR)
2570 : {
2571 0 : ChipLogError(Controller, "Failed to read Breadcrumb: %" CHIP_ERROR_FORMAT, err.Format());
2572 0 : return_err = err;
2573 : }
2574 :
2575 0 : err = mAttributeCache->Get<SupportsConcurrentConnection::TypeInfo>(kRootEndpointId, info.supportsConcurrentConnection);
2576 0 : if (err != CHIP_NO_ERROR)
2577 : {
2578 0 : ChipLogError(Controller, "Ignoring failure to read SupportsConcurrentConnection: %" CHIP_ERROR_FORMAT, err.Format());
2579 0 : info.supportsConcurrentConnection = true; // default to true (concurrent), not a fatal error
2580 : }
2581 :
2582 0 : err = mAttributeCache->Get<IsCommissioningWithoutPower::TypeInfo>(kRootEndpointId, info.general.isCommissioningWithoutPower);
2583 0 : if (err != CHIP_NO_ERROR)
2584 : {
2585 : // 'IsCommissioningWithoutPower' is optional. Any failures (likely not present) means default to assuming false.
2586 0 : info.general.isCommissioningWithoutPower = false;
2587 : }
2588 :
2589 0 : return return_err;
2590 : }
2591 :
2592 0 : CHIP_ERROR DeviceCommissioner::ParseBasicInformation(ReadCommissioningInfo & info)
2593 : {
2594 : using namespace BasicInformation::Attributes;
2595 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
2596 : CHIP_ERROR err;
2597 :
2598 0 : err = mAttributeCache->Get<VendorID::TypeInfo>(kRootEndpointId, info.basic.vendorId);
2599 0 : if (err != CHIP_NO_ERROR)
2600 : {
2601 0 : ChipLogError(Controller, "Failed to read VendorID: %" CHIP_ERROR_FORMAT, err.Format());
2602 0 : return_err = err;
2603 : }
2604 :
2605 0 : err = mAttributeCache->Get<ProductID::TypeInfo>(kRootEndpointId, info.basic.productId);
2606 0 : if (err != CHIP_NO_ERROR)
2607 : {
2608 0 : ChipLogError(Controller, "Failed to read ProductID: %" CHIP_ERROR_FORMAT, err.Format());
2609 0 : return_err = err;
2610 : }
2611 :
2612 0 : return return_err;
2613 : }
2614 :
2615 0 : CHIP_ERROR DeviceCommissioner::ParseNetworkCommissioningInfo(ReadCommissioningInfo & info)
2616 : {
2617 : using namespace NetworkCommissioning::Attributes;
2618 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
2619 : CHIP_ERROR err;
2620 :
2621 : // Set the network cluster endpoints first so we can match up the connection
2622 : // times. Note that here we don't know what endpoints the network
2623 : // commissioning clusters might be on.
2624 0 : err = mAttributeCache->ForEachAttribute(NetworkCommissioning::Id, [this, &info](const ConcreteAttributePath & path) {
2625 0 : VerifyOrReturnError(path.mAttributeId == FeatureMap::Id, CHIP_NO_ERROR);
2626 0 : BitFlags<NetworkCommissioning::Feature> features;
2627 0 : if (mAttributeCache->Get<FeatureMap::TypeInfo>(path, *features.RawStorage()) == CHIP_NO_ERROR)
2628 : {
2629 0 : if (features.Has(NetworkCommissioning::Feature::kWiFiNetworkInterface))
2630 : {
2631 0 : ChipLogProgress(Controller, "NetworkCommissioning Features: has WiFi. endpointid = %u", path.mEndpointId);
2632 0 : info.network.wifi.endpoint = path.mEndpointId;
2633 : }
2634 0 : else if (features.Has(NetworkCommissioning::Feature::kThreadNetworkInterface))
2635 : {
2636 0 : ChipLogProgress(Controller, "NetworkCommissioning Features: has Thread. endpointid = %u", path.mEndpointId);
2637 0 : info.network.thread.endpoint = path.mEndpointId;
2638 : }
2639 0 : else if (features.Has(NetworkCommissioning::Feature::kEthernetNetworkInterface))
2640 : {
2641 0 : ChipLogProgress(Controller, "NetworkCommissioning Features: has Ethernet. endpointid = %u", path.mEndpointId);
2642 0 : info.network.eth.endpoint = path.mEndpointId;
2643 : }
2644 : }
2645 0 : return CHIP_NO_ERROR;
2646 : });
2647 0 : AccumulateErrors(return_err, err);
2648 :
2649 0 : if (info.network.thread.endpoint != kInvalidEndpointId)
2650 : {
2651 0 : err = ParseNetworkCommissioningTimeouts(info.network.thread, "Thread");
2652 0 : AccumulateErrors(return_err, err);
2653 : }
2654 :
2655 0 : if (info.network.wifi.endpoint != kInvalidEndpointId)
2656 : {
2657 0 : err = ParseNetworkCommissioningTimeouts(info.network.wifi, "Wi-Fi");
2658 0 : AccumulateErrors(return_err, err);
2659 : }
2660 :
2661 0 : if (return_err != CHIP_NO_ERROR)
2662 : {
2663 0 : ChipLogError(Controller, "Failed to parse Network Commissioning information: %" CHIP_ERROR_FORMAT, return_err.Format());
2664 : }
2665 0 : return return_err;
2666 : }
2667 :
2668 0 : CHIP_ERROR DeviceCommissioner::ParseNetworkCommissioningTimeouts(NetworkClusterInfo & networkInfo, const char * networkType)
2669 : {
2670 : using namespace NetworkCommissioning::Attributes;
2671 :
2672 0 : CHIP_ERROR err = mAttributeCache->Get<ConnectMaxTimeSeconds::TypeInfo>(networkInfo.endpoint, networkInfo.minConnectionTime);
2673 0 : if (err != CHIP_NO_ERROR)
2674 : {
2675 0 : ChipLogError(Controller, "Failed to read %s ConnectMaxTimeSeconds (endpoint %u): %" CHIP_ERROR_FORMAT, networkType,
2676 : networkInfo.endpoint, err.Format());
2677 0 : return err;
2678 : }
2679 :
2680 0 : err = mAttributeCache->Get<ScanMaxTimeSeconds::TypeInfo>(networkInfo.endpoint, networkInfo.maxScanTime);
2681 0 : if (err != CHIP_NO_ERROR)
2682 : {
2683 : // We don't always read this attribute, and we read it as a wildcard, so
2684 : // don't treat it as an error simply because it's missing.
2685 0 : if (err != CHIP_ERROR_KEY_NOT_FOUND)
2686 : {
2687 0 : ChipLogError(Controller, "Failed to read %s ScanMaxTimeSeconds (endpoint: %u): %" CHIP_ERROR_FORMAT, networkType,
2688 : networkInfo.endpoint, err.Format());
2689 0 : return err;
2690 : }
2691 :
2692 : // Just flag as "we don't know".
2693 0 : networkInfo.maxScanTime = 0;
2694 : }
2695 :
2696 0 : return CHIP_NO_ERROR;
2697 : }
2698 :
2699 0 : CHIP_ERROR DeviceCommissioner::ParseTimeSyncInfo(ReadCommissioningInfo & info)
2700 : {
2701 : using namespace TimeSynchronization::Attributes;
2702 : CHIP_ERROR err;
2703 :
2704 : // If we fail to get the feature map, there's no viable time cluster, don't set anything.
2705 0 : BitFlags<TimeSynchronization::Feature> featureMap;
2706 0 : err = mAttributeCache->Get<FeatureMap::TypeInfo>(kRootEndpointId, *featureMap.RawStorage());
2707 0 : if (err != CHIP_NO_ERROR)
2708 : {
2709 0 : info.requiresUTC = false;
2710 0 : info.requiresTimeZone = false;
2711 0 : info.requiresDefaultNTP = false;
2712 0 : info.requiresTrustedTimeSource = false;
2713 0 : return CHIP_NO_ERROR;
2714 : }
2715 0 : info.requiresUTC = true;
2716 0 : info.requiresTimeZone = featureMap.Has(TimeSynchronization::Feature::kTimeZone);
2717 0 : info.requiresDefaultNTP = featureMap.Has(TimeSynchronization::Feature::kNTPClient);
2718 0 : info.requiresTrustedTimeSource = featureMap.Has(TimeSynchronization::Feature::kTimeSyncClient);
2719 :
2720 0 : if (info.requiresTimeZone)
2721 : {
2722 0 : err = mAttributeCache->Get<TimeZoneListMaxSize::TypeInfo>(kRootEndpointId, info.maxTimeZoneSize);
2723 0 : if (err != CHIP_NO_ERROR)
2724 : {
2725 : // This information should be available, let's do our best with what we have, but we can't set
2726 : // the time zone without this information
2727 0 : info.requiresTimeZone = false;
2728 : }
2729 0 : err = mAttributeCache->Get<DSTOffsetListMaxSize::TypeInfo>(kRootEndpointId, info.maxDSTSize);
2730 0 : if (err != CHIP_NO_ERROR)
2731 : {
2732 0 : info.requiresTimeZone = false;
2733 : }
2734 : }
2735 0 : if (info.requiresDefaultNTP)
2736 : {
2737 0 : DefaultNTP::TypeInfo::DecodableType defaultNTP;
2738 0 : err = mAttributeCache->Get<DefaultNTP::TypeInfo>(kRootEndpointId, defaultNTP);
2739 0 : if (err == CHIP_NO_ERROR && (!defaultNTP.IsNull()) && (defaultNTP.Value().size() != 0))
2740 : {
2741 0 : info.requiresDefaultNTP = false;
2742 : }
2743 : }
2744 0 : if (info.requiresTrustedTimeSource)
2745 : {
2746 0 : TrustedTimeSource::TypeInfo::DecodableType trustedTimeSource;
2747 0 : err = mAttributeCache->Get<TrustedTimeSource::TypeInfo>(kRootEndpointId, trustedTimeSource);
2748 0 : if (err == CHIP_NO_ERROR && !trustedTimeSource.IsNull())
2749 : {
2750 0 : info.requiresTrustedTimeSource = false;
2751 : }
2752 : }
2753 :
2754 0 : return CHIP_NO_ERROR;
2755 : }
2756 :
2757 0 : CHIP_ERROR DeviceCommissioner::ParseFabrics(ReadCommissioningInfo & info)
2758 : {
2759 : using namespace OperationalCredentials::Attributes;
2760 : CHIP_ERROR err;
2761 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
2762 :
2763 : // We might not have requested a Fabrics attribute at all, so not having a
2764 : // value for it is not an error.
2765 0 : err = mAttributeCache->ForEachAttribute(OperationalCredentials::Id, [this, &info](const ConcreteAttributePath & path) {
2766 : using namespace chip::app::Clusters::OperationalCredentials::Attributes;
2767 : // this code is checking if the device is already on the commissioner's fabric.
2768 : // if a matching fabric is found, then remember the nodeId so that the commissioner
2769 : // can, if it decides to, cancel commissioning (before it fails in AddNoc) and know
2770 : // the device's nodeId on its fabric.
2771 0 : switch (path.mAttributeId)
2772 : {
2773 0 : case Fabrics::Id: {
2774 0 : Fabrics::TypeInfo::DecodableType fabrics;
2775 0 : ReturnErrorOnFailure(this->mAttributeCache->Get<Fabrics::TypeInfo>(path, fabrics));
2776 : // this is a best effort attempt to find a matching fabric, so no error checking on iter
2777 0 : auto iter = fabrics.begin();
2778 0 : while (iter.Next())
2779 : {
2780 0 : auto & fabricDescriptor = iter.GetValue();
2781 0 : ChipLogProgress(Controller,
2782 : "DeviceCommissioner::OnDone - fabric.vendorId=0x%04X fabric.fabricId=0x" ChipLogFormatX64
2783 : " fabric.nodeId=0x" ChipLogFormatX64,
2784 : fabricDescriptor.vendorID, ChipLogValueX64(fabricDescriptor.fabricID),
2785 : ChipLogValueX64(fabricDescriptor.nodeID));
2786 0 : if (GetFabricId() == fabricDescriptor.fabricID)
2787 : {
2788 0 : ChipLogProgress(Controller, "DeviceCommissioner::OnDone - found a matching fabric id");
2789 0 : chip::ByteSpan rootKeySpan = fabricDescriptor.rootPublicKey;
2790 0 : if (rootKeySpan.size() != Crypto::kP256_PublicKey_Length)
2791 : {
2792 0 : ChipLogError(Controller, "DeviceCommissioner::OnDone - fabric root key size mismatch %u != %u",
2793 : static_cast<unsigned>(rootKeySpan.size()),
2794 : static_cast<unsigned>(Crypto::kP256_PublicKey_Length));
2795 0 : continue;
2796 : }
2797 0 : P256PublicKeySpan rootPubKeySpan(rootKeySpan.data());
2798 0 : Crypto::P256PublicKey deviceRootPublicKey(rootPubKeySpan);
2799 :
2800 0 : Crypto::P256PublicKey commissionerRootPublicKey;
2801 0 : if (CHIP_NO_ERROR != GetRootPublicKey(commissionerRootPublicKey))
2802 : {
2803 0 : ChipLogError(Controller, "DeviceCommissioner::OnDone - error reading commissioner root public key");
2804 : }
2805 0 : else if (commissionerRootPublicKey.Matches(deviceRootPublicKey))
2806 : {
2807 0 : ChipLogProgress(Controller, "DeviceCommissioner::OnDone - fabric root keys match");
2808 0 : info.remoteNodeId = fabricDescriptor.nodeID;
2809 : }
2810 0 : }
2811 : }
2812 :
2813 0 : return CHIP_NO_ERROR;
2814 : }
2815 0 : default:
2816 0 : return CHIP_NO_ERROR;
2817 : }
2818 : });
2819 :
2820 0 : if (mPairingDelegate != nullptr)
2821 : {
2822 0 : mPairingDelegate->OnFabricCheck(info.remoteNodeId);
2823 : }
2824 :
2825 0 : return return_err;
2826 : }
2827 :
2828 2 : CHIP_ERROR DeviceCommissioner::ParseICDInfo(ReadCommissioningInfo & info)
2829 : {
2830 : using namespace IcdManagement::Attributes;
2831 : CHIP_ERROR err;
2832 :
2833 2 : bool hasUserActiveModeTrigger = false;
2834 2 : bool isICD = false;
2835 :
2836 2 : BitFlags<IcdManagement::Feature> featureMap;
2837 2 : err = mAttributeCache->Get<FeatureMap::TypeInfo>(kRootEndpointId, *featureMap.RawStorage());
2838 4 : if (err == CHIP_NO_ERROR)
2839 : {
2840 2 : info.icd.isLIT = featureMap.Has(IcdManagement::Feature::kLongIdleTimeSupport);
2841 2 : info.icd.checkInProtocolSupport = featureMap.Has(IcdManagement::Feature::kCheckInProtocolSupport);
2842 2 : hasUserActiveModeTrigger = featureMap.Has(IcdManagement::Feature::kUserActiveModeTrigger);
2843 2 : isICD = true;
2844 :
2845 : // LIT support was introduced but broken in ICD Management cluster revision 2 (Matter 1.3).
2846 : // Only treat a device as LIT for cluster revisions after 1.3 (i.e., revision > 2).
2847 2 : if (info.icd.isLIT)
2848 : {
2849 2 : uint16_t clusterRevision = 0;
2850 2 : CHIP_ERROR revErr = mAttributeCache->Get<ClusterRevision::TypeInfo>(kRootEndpointId, clusterRevision);
2851 4 : if (revErr != CHIP_NO_ERROR || clusterRevision <= 2)
2852 : {
2853 2 : if (revErr == CHIP_NO_ERROR)
2854 : {
2855 1 : ChipLogProgress(Controller,
2856 : "IcdManagement: Device claims LIT support but cluster revision is %" PRIu16
2857 : " (Matter 1.3). Disabling LIT due to known Matter 1.3 LIT issues.",
2858 : clusterRevision);
2859 : }
2860 : else
2861 : {
2862 0 : ChipLogProgress(Controller,
2863 : "IcdManagement: Device claims LIT support but ClusterRevision attribute is "
2864 : "missing or unreadable (err=%" CHIP_ERROR_FORMAT
2865 : "). Treating as revision <= 2 and disabling LIT.",
2866 : revErr.Format());
2867 : }
2868 1 : info.icd.isLIT = false;
2869 : }
2870 : }
2871 : }
2872 0 : else if (err == CHIP_ERROR_KEY_NOT_FOUND)
2873 : {
2874 : // This key is optional so not an error
2875 0 : info.icd.isLIT = false;
2876 0 : err = CHIP_NO_ERROR;
2877 : }
2878 0 : else if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
2879 : {
2880 0 : app::StatusIB statusIB;
2881 0 : err = mAttributeCache->GetStatus(app::ConcreteAttributePath(kRootEndpointId, IcdManagement::Id, FeatureMap::Id), statusIB);
2882 0 : if (err == CHIP_NO_ERROR)
2883 : {
2884 0 : if (statusIB.mStatus == Protocols::InteractionModel::Status::UnsupportedCluster)
2885 : {
2886 0 : info.icd.isLIT = false;
2887 : }
2888 : else
2889 : {
2890 0 : err = statusIB.ToChipError();
2891 : }
2892 : }
2893 : }
2894 :
2895 2 : ReturnErrorOnFailure(err);
2896 :
2897 2 : info.icd.userActiveModeTriggerHint.ClearAll();
2898 2 : info.icd.userActiveModeTriggerInstruction = CharSpan();
2899 :
2900 2 : if (hasUserActiveModeTrigger)
2901 : {
2902 : // Intentionally ignore errors since they are not mandatory.
2903 0 : bool activeModeTriggerInstructionRequired = false;
2904 :
2905 0 : err = mAttributeCache->Get<UserActiveModeTriggerHint::TypeInfo>(kRootEndpointId, info.icd.userActiveModeTriggerHint);
2906 0 : if (err != CHIP_NO_ERROR)
2907 : {
2908 0 : ChipLogError(Controller, "IcdManagement.UserActiveModeTriggerHint expected, but failed to read.");
2909 0 : return err;
2910 : }
2911 :
2912 : using IcdManagement::UserActiveModeTriggerBitmap;
2913 0 : activeModeTriggerInstructionRequired = info.icd.userActiveModeTriggerHint.HasAny(
2914 0 : UserActiveModeTriggerBitmap::kCustomInstruction, UserActiveModeTriggerBitmap::kActuateSensorSeconds,
2915 0 : UserActiveModeTriggerBitmap::kActuateSensorTimes, UserActiveModeTriggerBitmap::kActuateSensorLightsBlink,
2916 0 : UserActiveModeTriggerBitmap::kResetButtonLightsBlink, UserActiveModeTriggerBitmap::kResetButtonSeconds,
2917 0 : UserActiveModeTriggerBitmap::kResetButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonSeconds,
2918 0 : UserActiveModeTriggerBitmap::kSetupButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonTimes,
2919 0 : UserActiveModeTriggerBitmap::kAppDefinedButton);
2920 :
2921 0 : if (activeModeTriggerInstructionRequired)
2922 : {
2923 0 : err = mAttributeCache->Get<UserActiveModeTriggerInstruction::TypeInfo>(kRootEndpointId,
2924 0 : info.icd.userActiveModeTriggerInstruction);
2925 0 : if (err != CHIP_NO_ERROR)
2926 : {
2927 0 : ChipLogError(Controller,
2928 : "IcdManagement.UserActiveModeTriggerInstruction expected for given active mode trigger hint, but "
2929 : "failed to read.");
2930 0 : return err;
2931 : }
2932 : }
2933 : }
2934 :
2935 2 : if (!isICD)
2936 : {
2937 0 : info.icd.idleModeDuration = 0;
2938 0 : info.icd.activeModeDuration = 0;
2939 0 : info.icd.activeModeThreshold = 0;
2940 0 : return CHIP_NO_ERROR;
2941 : }
2942 :
2943 2 : err = mAttributeCache->Get<IdleModeDuration::TypeInfo>(kRootEndpointId, info.icd.idleModeDuration);
2944 4 : if (err != CHIP_NO_ERROR)
2945 : {
2946 0 : ChipLogError(Controller, "IcdManagement.IdleModeDuration expected, but failed to read: %" CHIP_ERROR_FORMAT, err.Format());
2947 0 : return err;
2948 : }
2949 :
2950 2 : err = mAttributeCache->Get<ActiveModeDuration::TypeInfo>(kRootEndpointId, info.icd.activeModeDuration);
2951 4 : if (err != CHIP_NO_ERROR)
2952 : {
2953 0 : ChipLogError(Controller, "IcdManagement.ActiveModeDuration expected, but failed to read: %" CHIP_ERROR_FORMAT,
2954 : err.Format());
2955 0 : return err;
2956 : }
2957 :
2958 2 : err = mAttributeCache->Get<ActiveModeThreshold::TypeInfo>(kRootEndpointId, info.icd.activeModeThreshold);
2959 4 : if (err != CHIP_NO_ERROR)
2960 : {
2961 0 : ChipLogError(Controller, "IcdManagement.ActiveModeThreshold expected, but failed to read: %" CHIP_ERROR_FORMAT,
2962 : err.Format());
2963 : }
2964 :
2965 2 : return err;
2966 : }
2967 :
2968 0 : void DeviceCommissioner::OnArmFailSafe(void * context,
2969 : const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
2970 : {
2971 0 : CommissioningDelegate::CommissioningReport report;
2972 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2973 :
2974 0 : ChipLogProgress(Controller, "Received ArmFailSafe response errorCode=%u", to_underlying(data.errorCode));
2975 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
2976 : {
2977 0 : err = CHIP_ERROR_INTERNAL;
2978 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
2979 : }
2980 :
2981 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2982 0 : commissioner->CommissioningStageComplete(err, report);
2983 0 : }
2984 :
2985 0 : void DeviceCommissioner::OnSetRegulatoryConfigResponse(
2986 : void * context, const GeneralCommissioning::Commands::SetRegulatoryConfigResponse::DecodableType & data)
2987 : {
2988 0 : CommissioningDelegate::CommissioningReport report;
2989 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2990 :
2991 0 : ChipLogProgress(Controller, "Received SetRegulatoryConfig response errorCode=%u", to_underlying(data.errorCode));
2992 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
2993 : {
2994 0 : err = CHIP_ERROR_INTERNAL;
2995 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
2996 : }
2997 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2998 0 : commissioner->CommissioningStageComplete(err, report);
2999 0 : }
3000 :
3001 0 : void DeviceCommissioner::OnSetTCAcknowledgementsResponse(
3002 : void * context, const GeneralCommissioning::Commands::SetTCAcknowledgementsResponse::DecodableType & data)
3003 : {
3004 0 : CommissioningDelegate::CommissioningReport report;
3005 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3006 :
3007 0 : ChipLogProgress(Controller, "Received SetTCAcknowledgements response errorCode=%u", to_underlying(data.errorCode));
3008 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
3009 : {
3010 0 : err = CHIP_ERROR_INTERNAL;
3011 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
3012 : }
3013 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3014 0 : commissioner->CommissioningStageComplete(err, report);
3015 0 : }
3016 :
3017 0 : void DeviceCommissioner::OnSetTimeZoneResponse(void * context,
3018 : const TimeSynchronization::Commands::SetTimeZoneResponse::DecodableType & data)
3019 : {
3020 0 : CommissioningDelegate::CommissioningReport report;
3021 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3022 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3023 : TimeZoneResponseInfo info;
3024 0 : info.requiresDSTOffsets = data.DSTOffsetRequired;
3025 0 : report.Set<TimeZoneResponseInfo>(info);
3026 0 : commissioner->CommissioningStageComplete(err, report);
3027 0 : }
3028 :
3029 0 : void DeviceCommissioner::OnSetUTCError(void * context, CHIP_ERROR error)
3030 : {
3031 : // For SetUTCTime, we don't actually care if the commissionee didn't want out time, that's its choice
3032 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3033 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
3034 0 : }
3035 :
3036 0 : void DeviceCommissioner::OnScanNetworksFailure(void * context, CHIP_ERROR error)
3037 : {
3038 0 : ChipLogProgress(Controller, "Received ScanNetworks failure response %" CHIP_ERROR_FORMAT, error.Format());
3039 :
3040 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3041 :
3042 : // advance to the kNeedsNetworkCreds waiting step
3043 : // clear error so that we don't abort the commissioning when ScanNetworks fails
3044 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
3045 :
3046 0 : if (commissioner->GetPairingDelegate() != nullptr)
3047 : {
3048 0 : commissioner->GetPairingDelegate()->OnScanNetworksFailure(error);
3049 : }
3050 0 : }
3051 :
3052 0 : void DeviceCommissioner::OnScanNetworksResponse(void * context,
3053 : const NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & data)
3054 : {
3055 0 : CommissioningDelegate::CommissioningReport report;
3056 :
3057 0 : ChipLogProgress(Controller, "Received ScanNetwork response, networkingStatus=%u debugText=%s",
3058 : to_underlying(data.networkingStatus),
3059 : (data.debugText.HasValue() ? std::string(data.debugText.Value().data(), data.debugText.Value().size()).c_str()
3060 : : "none provided"));
3061 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3062 :
3063 : // advance to the kNeedsNetworkCreds waiting step
3064 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
3065 :
3066 0 : if (commissioner->GetPairingDelegate() != nullptr)
3067 : {
3068 0 : commissioner->GetPairingDelegate()->OnScanNetworksSuccess(data);
3069 : }
3070 0 : }
3071 :
3072 0 : CHIP_ERROR DeviceCommissioner::NetworkCredentialsReady()
3073 : {
3074 0 : VerifyOrReturnError(mCommissioningStage == CommissioningStage::kNeedsNetworkCreds, CHIP_ERROR_INCORRECT_STATE);
3075 :
3076 : // need to advance to next step
3077 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3078 :
3079 0 : return CHIP_NO_ERROR;
3080 : }
3081 :
3082 0 : CHIP_ERROR DeviceCommissioner::ICDRegistrationInfoReady()
3083 : {
3084 0 : VerifyOrReturnError(mCommissioningStage == CommissioningStage::kICDGetRegistrationInfo, CHIP_ERROR_INCORRECT_STATE);
3085 :
3086 : // need to advance to next step
3087 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3088 :
3089 0 : return CHIP_NO_ERROR;
3090 : }
3091 :
3092 0 : void DeviceCommissioner::OnNetworkConfigResponse(void * context,
3093 : const NetworkCommissioning::Commands::NetworkConfigResponse::DecodableType & data)
3094 : {
3095 0 : CommissioningDelegate::CommissioningReport report;
3096 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3097 :
3098 0 : ChipLogProgress(Controller, "Received NetworkConfig response, networkingStatus=%u", to_underlying(data.networkingStatus));
3099 0 : if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
3100 : {
3101 0 : err = CHIP_ERROR_INTERNAL;
3102 0 : report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
3103 : }
3104 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3105 0 : commissioner->CommissioningStageComplete(err, report);
3106 0 : }
3107 :
3108 0 : void DeviceCommissioner::OnConnectNetworkResponse(
3109 : void * context, const NetworkCommissioning::Commands::ConnectNetworkResponse::DecodableType & data)
3110 : {
3111 0 : CommissioningDelegate::CommissioningReport report;
3112 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3113 :
3114 0 : ChipLogProgress(Controller, "Received ConnectNetwork response, networkingStatus=%u", to_underlying(data.networkingStatus));
3115 0 : if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
3116 : {
3117 0 : err = CHIP_ERROR_INTERNAL;
3118 0 : report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
3119 : }
3120 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3121 0 : commissioner->CommissioningStageComplete(err, report);
3122 0 : }
3123 :
3124 0 : void DeviceCommissioner::OnCommissioningCompleteResponse(
3125 : void * context, const GeneralCommissioning::Commands::CommissioningCompleteResponse::DecodableType & data)
3126 : {
3127 0 : CommissioningDelegate::CommissioningReport report;
3128 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3129 :
3130 0 : ChipLogProgress(Controller, "Received CommissioningComplete response, errorCode=%u", to_underlying(data.errorCode));
3131 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
3132 : {
3133 0 : err = CHIP_ERROR_INTERNAL;
3134 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
3135 : }
3136 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
3137 0 : commissioner->CommissioningStageComplete(err, report);
3138 0 : }
3139 :
3140 : template <typename RequestObjectT>
3141 : CHIP_ERROR
3142 0 : DeviceCommissioner::SendCommissioningCommand(DeviceProxy * device, const RequestObjectT & request,
3143 : CommandResponseSuccessCallback<typename RequestObjectT::ResponseType> successCb,
3144 : CommandResponseFailureCallback failureCb, EndpointId endpoint,
3145 : Optional<System::Clock::Timeout> timeout, bool fireAndForget)
3146 :
3147 : {
3148 : // Default behavior is to make sequential, cancellable calls tracked via mInvokeCancelFn.
3149 : // Fire-and-forget calls are not cancellable and don't receive `this` as context in callbacks.
3150 0 : VerifyOrDie(fireAndForget || !mInvokeCancelFn); // we don't make parallel (cancellable) calls
3151 :
3152 0 : void * context = (!fireAndForget) ? this : nullptr;
3153 0 : auto onSuccessCb = [context, successCb](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus,
3154 : const typename RequestObjectT::ResponseType & responseData) {
3155 0 : successCb(context, responseData);
3156 : };
3157 0 : auto onFailureCb = [context, failureCb](CHIP_ERROR aError) { failureCb(context, aError); };
3158 :
3159 0 : return InvokeCommandRequest(device->GetExchangeManager(), device->GetSecureSession().Value(), endpoint, request, onSuccessCb,
3160 0 : onFailureCb, NullOptional, timeout, (!fireAndForget) ? &mInvokeCancelFn : nullptr);
3161 : }
3162 :
3163 : template <typename AttrType>
3164 : CHIP_ERROR DeviceCommissioner::SendCommissioningWriteRequest(DeviceProxy * device, EndpointId endpoint, ClusterId cluster,
3165 : AttributeId attribute, const AttrType & requestData,
3166 : WriteResponseSuccessCallback successCb,
3167 : WriteResponseFailureCallback failureCb)
3168 : {
3169 : VerifyOrDie(!mWriteCancelFn); // we don't make parallel (cancellable) calls
3170 : auto onSuccessCb = [this, successCb](const app::ConcreteAttributePath & aPath) { successCb(this); };
3171 : auto onFailureCb = [this, failureCb](const app::ConcreteAttributePath * aPath, CHIP_ERROR aError) { failureCb(this, aError); };
3172 : return WriteAttribute(device->GetSecureSession().Value(), endpoint, cluster, attribute, requestData, onSuccessCb, onFailureCb,
3173 : /* aTimedWriteTimeoutMs = */ NullOptional, /* onDoneCb = */ nullptr, /* aDataVersion = */ NullOptional,
3174 : /* outCancelFn = */ &mWriteCancelFn);
3175 : }
3176 :
3177 0 : void DeviceCommissioner::SendCommissioningReadRequest(DeviceProxy * proxy, Optional<System::Clock::Timeout> timeout,
3178 : app::AttributePathParams * readPaths, size_t readPathsSize)
3179 : {
3180 0 : VerifyOrDie(!mReadClient); // we don't perform parallel reads
3181 :
3182 0 : app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
3183 0 : app::ReadPrepareParams readParams(proxy->GetSecureSession().Value());
3184 0 : readParams.mIsFabricFiltered = false;
3185 0 : if (timeout.HasValue())
3186 : {
3187 0 : readParams.mTimeout = timeout.Value();
3188 : }
3189 0 : readParams.mpAttributePathParamsList = readPaths;
3190 0 : readParams.mAttributePathParamsListSize = readPathsSize;
3191 :
3192 : // Take ownership of the attribute cache, so it can be released if SendRequest fails.
3193 0 : auto attributeCache = std::move(mAttributeCache);
3194 : auto readClient = chip::Platform::MakeUnique<app::ReadClient>(
3195 0 : engine, proxy->GetExchangeManager(), attributeCache->GetBufferedCallback(), app::ReadClient::InteractionType::Read);
3196 0 : CHIP_ERROR err = readClient->SendRequest(readParams);
3197 0 : if (err != CHIP_NO_ERROR)
3198 : {
3199 0 : ChipLogError(Controller, "Failed to send read request: %" CHIP_ERROR_FORMAT, err.Format());
3200 0 : CommissioningStageComplete(err);
3201 0 : return;
3202 : }
3203 0 : mAttributeCache = std::move(attributeCache);
3204 0 : mReadClient = std::move(readClient);
3205 0 : }
3206 :
3207 0 : void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, CommissioningStage step, CommissioningParameters & params,
3208 : CommissioningDelegate * delegate, EndpointId endpoint,
3209 : Optional<System::Clock::Timeout> timeout)
3210 :
3211 : {
3212 : MATTER_LOG_METRIC(kMetricDeviceCommissionerCommissionStage, step);
3213 : MATTER_LOG_METRIC_BEGIN(MetricKeyForCommissioningStage(step));
3214 :
3215 0 : if (params.GetCompletionStatus().err == CHIP_NO_ERROR)
3216 : {
3217 0 : ChipLogProgress(Controller, "Performing next commissioning step '%s'", StageToString(step));
3218 : }
3219 : else
3220 : {
3221 0 : ChipLogProgress(Controller, "Performing next commissioning step '%s' with completion status = '%s'", StageToString(step),
3222 : params.GetCompletionStatus().err.AsString());
3223 : }
3224 :
3225 0 : if (mPairingDelegate)
3226 : {
3227 0 : mPairingDelegate->OnCommissioningStageStart(PeerId(GetCompressedFabricId(), proxy->GetDeviceId()), step);
3228 : }
3229 :
3230 0 : mCommissioningStepTimeout = timeout;
3231 0 : mCommissioningStage = step;
3232 0 : mCommissioningDelegate = delegate;
3233 0 : mDeviceBeingCommissioned = proxy;
3234 :
3235 : // TODO: Extend timeouts to the DAC and Opcert requests.
3236 : // TODO(cecille): We probably want something better than this for breadcrumbs.
3237 0 : uint64_t breadcrumb = static_cast<uint64_t>(step);
3238 :
3239 0 : switch (step)
3240 : {
3241 0 : case CommissioningStage::kArmFailsafe: {
3242 0 : VerifyOrDie(endpoint == kRootEndpointId);
3243 : // Make sure the fail-safe value we set here actually ends up being used
3244 : // no matter what.
3245 0 : proxy->SetFailSafeExpirationTimestamp(System::Clock::kZero);
3246 0 : VerifyOrDie(ExtendArmFailSafeInternal(proxy, step, params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout),
3247 : timeout, OnArmFailSafe, OnBasicFailure, /* fireAndForget = */ false));
3248 : }
3249 0 : break;
3250 0 : case CommissioningStage::kReadCommissioningInfo: {
3251 0 : VerifyOrDie(endpoint == kRootEndpointId);
3252 0 : ChipLogProgress(Controller, "Sending read requests for commissioning information");
3253 :
3254 : // Allocate a ClusterStateCache to collect the data from our read requests.
3255 : // The cache will be released in:
3256 : // - SendCommissioningReadRequest when failing to send a read request.
3257 : // - FinishReadingCommissioningInfo when the ReadCommissioningInfo stage is completed.
3258 : // - CancelCommissioningInteractions
3259 0 : mAttributeCache = Platform::MakeUnique<app::ClusterStateCache>(*this);
3260 :
3261 : // Generally we need to make more than one read request, because as per spec a server only
3262 : // supports a limited number of paths per Read Interaction. Because the actual number of
3263 : // interactions we end up performing is dynamic, we track all of them within a single
3264 : // commissioning stage.
3265 0 : mReadCommissioningInfoProgress = 0;
3266 0 : ContinueReadingCommissioningInfo(params); // Note: assume params == delegate.GetCommissioningParameters()
3267 0 : break;
3268 : }
3269 0 : case CommissioningStage::kConfigureUTCTime: {
3270 0 : TimeSynchronization::Commands::SetUTCTime::Type request;
3271 0 : uint64_t kChipEpochUsSinceUnixEpoch = static_cast<uint64_t>(kChipEpochSecondsSinceUnixEpoch) * chip::kMicrosecondsPerSecond;
3272 : System::Clock::Microseconds64 utcTime;
3273 0 : if (System::SystemClock().GetClock_RealTime(utcTime) != CHIP_NO_ERROR || utcTime.count() <= kChipEpochUsSinceUnixEpoch)
3274 : {
3275 : // We have no time to give, but that's OK, just complete this stage
3276 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3277 0 : return;
3278 : }
3279 :
3280 0 : request.UTCTime = utcTime.count() - kChipEpochUsSinceUnixEpoch;
3281 : // For now, we assume a seconds granularity
3282 0 : request.granularity = TimeSynchronization::GranularityEnum::kSecondsGranularity;
3283 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnSetUTCError, endpoint, timeout);
3284 0 : if (err != CHIP_NO_ERROR)
3285 : {
3286 : // We won't get any async callbacks here, so just complete our stage.
3287 0 : ChipLogError(Controller, "Failed to send SetUTCTime command: %" CHIP_ERROR_FORMAT, err.Format());
3288 0 : CommissioningStageComplete(err);
3289 0 : return;
3290 : }
3291 0 : break;
3292 : }
3293 0 : case CommissioningStage::kConfigureTimeZone: {
3294 0 : if (!params.GetTimeZone().HasValue())
3295 : {
3296 0 : ChipLogError(Controller, "ConfigureTimeZone stage called with no time zone data");
3297 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3298 0 : return;
3299 : }
3300 0 : TimeSynchronization::Commands::SetTimeZone::Type request;
3301 0 : request.timeZone = params.GetTimeZone().Value();
3302 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnSetTimeZoneResponse, OnBasicFailure, endpoint, timeout);
3303 0 : if (err != CHIP_NO_ERROR)
3304 : {
3305 : // We won't get any async callbacks here, so just complete our stage.
3306 0 : ChipLogError(Controller, "Failed to send SetTimeZone command: %" CHIP_ERROR_FORMAT, err.Format());
3307 0 : CommissioningStageComplete(err);
3308 0 : return;
3309 : }
3310 0 : break;
3311 : }
3312 0 : case CommissioningStage::kConfigureDSTOffset: {
3313 0 : if (!params.GetDSTOffsets().HasValue())
3314 : {
3315 0 : ChipLogError(Controller, "ConfigureDSTOffset stage called with no DST data");
3316 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3317 0 : return;
3318 : }
3319 0 : TimeSynchronization::Commands::SetDSTOffset::Type request;
3320 0 : request.DSTOffset = params.GetDSTOffsets().Value();
3321 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
3322 0 : if (err != CHIP_NO_ERROR)
3323 : {
3324 : // We won't get any async callbacks here, so just complete our stage.
3325 0 : ChipLogError(Controller, "Failed to send SetDSTOffset command: %" CHIP_ERROR_FORMAT, err.Format());
3326 0 : CommissioningStageComplete(err);
3327 0 : return;
3328 : }
3329 0 : break;
3330 : }
3331 0 : case CommissioningStage::kConfigureDefaultNTP: {
3332 0 : if (!params.GetDefaultNTP().HasValue())
3333 : {
3334 0 : ChipLogError(Controller, "ConfigureDefaultNTP stage called with no default NTP data");
3335 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3336 0 : return;
3337 : }
3338 0 : TimeSynchronization::Commands::SetDefaultNTP::Type request;
3339 0 : request.defaultNTP = params.GetDefaultNTP().Value();
3340 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
3341 0 : if (err != CHIP_NO_ERROR)
3342 : {
3343 : // We won't get any async callbacks here, so just complete our stage.
3344 0 : ChipLogError(Controller, "Failed to send SetDefaultNTP command: %" CHIP_ERROR_FORMAT, err.Format());
3345 0 : CommissioningStageComplete(err);
3346 0 : return;
3347 : }
3348 0 : break;
3349 : }
3350 0 : case CommissioningStage::kScanNetworks: {
3351 0 : NetworkCommissioning::Commands::ScanNetworks::Type request;
3352 0 : if (params.GetWiFiCredentials().HasValue())
3353 : {
3354 0 : request.ssid.Emplace(params.GetWiFiCredentials().Value().ssid);
3355 : }
3356 0 : request.breadcrumb.Emplace(breadcrumb);
3357 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnScanNetworksResponse, OnScanNetworksFailure, endpoint, timeout);
3358 0 : if (err != CHIP_NO_ERROR)
3359 : {
3360 : // We won't get any async callbacks here, so just complete our stage.
3361 0 : ChipLogError(Controller, "Failed to send ScanNetworks command: %" CHIP_ERROR_FORMAT, err.Format());
3362 0 : CommissioningStageComplete(err);
3363 0 : return;
3364 : }
3365 0 : break;
3366 : }
3367 0 : case CommissioningStage::kNeedsNetworkCreds: {
3368 : // Nothing to do.
3369 : //
3370 : // Either we did a scan and the OnScanNetworksSuccess and OnScanNetworksFailure
3371 : // callbacks will tell the DevicePairingDelegate that network credentials are
3372 : // needed, or we asked the DevicePairingDelegate for network credentials
3373 : // explicitly, and are waiting for it to get back to us.
3374 0 : break;
3375 : }
3376 0 : case CommissioningStage::kConfigRegulatory: {
3377 : // TODO(cecille): Worthwhile to keep this around as part of the class?
3378 : // TODO(cecille): Where is the country config actually set?
3379 0 : ChipLogProgress(Controller, "Setting Regulatory Config");
3380 : auto capability =
3381 0 : params.GetLocationCapability().ValueOr(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor);
3382 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum regulatoryConfig;
3383 : // Value is only switchable on the devices with indoor/outdoor capability
3384 0 : if (capability == app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kIndoorOutdoor)
3385 : {
3386 : // If the device supports indoor and outdoor configs, use the setting from the commissioner, otherwise fall back to
3387 : // the current device setting then to outdoor (most restrictive)
3388 0 : if (params.GetDeviceRegulatoryLocation().HasValue())
3389 : {
3390 0 : regulatoryConfig = params.GetDeviceRegulatoryLocation().Value();
3391 0 : ChipLogProgress(Controller, "Setting regulatory config to %u from commissioner override",
3392 : static_cast<uint8_t>(regulatoryConfig));
3393 : }
3394 0 : else if (params.GetDefaultRegulatoryLocation().HasValue())
3395 : {
3396 0 : regulatoryConfig = params.GetDefaultRegulatoryLocation().Value();
3397 0 : ChipLogProgress(Controller, "No regulatory config supplied by controller, leaving as device default (%u)",
3398 : static_cast<uint8_t>(regulatoryConfig));
3399 : }
3400 : else
3401 : {
3402 0 : regulatoryConfig = app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor;
3403 0 : ChipLogProgress(Controller, "No overrride or device regulatory config supplied, setting to outdoor");
3404 : }
3405 : }
3406 : else
3407 : {
3408 0 : ChipLogProgress(Controller, "Device does not support configurable regulatory location");
3409 0 : regulatoryConfig = capability;
3410 : }
3411 :
3412 0 : CharSpan countryCode;
3413 0 : const auto & providedCountryCode = params.GetCountryCode();
3414 0 : if (providedCountryCode.HasValue())
3415 : {
3416 0 : countryCode = providedCountryCode.Value();
3417 : }
3418 : else
3419 : {
3420 : // Default to "XX", for lack of anything better.
3421 0 : countryCode = "XX"_span;
3422 : }
3423 :
3424 0 : GeneralCommissioning::Commands::SetRegulatoryConfig::Type request;
3425 0 : request.newRegulatoryConfig = regulatoryConfig;
3426 0 : request.countryCode = countryCode;
3427 0 : request.breadcrumb = breadcrumb;
3428 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnSetRegulatoryConfigResponse, OnBasicFailure, endpoint, timeout);
3429 0 : if (err != CHIP_NO_ERROR)
3430 : {
3431 : // We won't get any async callbacks here, so just complete our stage.
3432 0 : ChipLogError(Controller, "Failed to send SetRegulatoryConfig command: %" CHIP_ERROR_FORMAT, err.Format());
3433 0 : CommissioningStageComplete(err);
3434 0 : return;
3435 : }
3436 : }
3437 0 : break;
3438 0 : case CommissioningStage::kConfigureTCAcknowledgments: {
3439 0 : ChipLogProgress(Controller, "Setting Terms and Conditions");
3440 :
3441 0 : if (!params.GetTermsAndConditionsAcknowledgement().HasValue())
3442 : {
3443 0 : ChipLogProgress(Controller, "Setting Terms and Conditions: Skipped");
3444 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3445 0 : return;
3446 : }
3447 :
3448 0 : GeneralCommissioning::Commands::SetTCAcknowledgements::Type request;
3449 0 : TermsAndConditionsAcknowledgement termsAndConditionsAcknowledgement = params.GetTermsAndConditionsAcknowledgement().Value();
3450 0 : request.TCUserResponse = termsAndConditionsAcknowledgement.acceptedTermsAndConditions;
3451 0 : request.TCVersion = termsAndConditionsAcknowledgement.acceptedTermsAndConditionsVersion;
3452 :
3453 0 : ChipLogProgress(Controller, "Setting Terms and Conditions: %hu, %hu", request.TCUserResponse, request.TCVersion);
3454 : CHIP_ERROR err =
3455 0 : SendCommissioningCommand(proxy, request, OnSetTCAcknowledgementsResponse, OnBasicFailure, endpoint, timeout);
3456 0 : if (err != CHIP_NO_ERROR)
3457 : {
3458 0 : ChipLogError(Controller, "Failed to send SetTCAcknowledgements command: %" CHIP_ERROR_FORMAT, err.Format());
3459 0 : CommissioningStageComplete(err);
3460 0 : return;
3461 : }
3462 0 : break;
3463 : }
3464 0 : case CommissioningStage::kSendPAICertificateRequest: {
3465 0 : ChipLogProgress(Controller, "Sending request for PAI certificate");
3466 0 : CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kPAI, timeout);
3467 0 : if (err != CHIP_NO_ERROR)
3468 : {
3469 : // We won't get any async callbacks here, so just complete our stage.
3470 0 : ChipLogError(Controller, "Failed to send CertificateChainRequest command to get PAI: %" CHIP_ERROR_FORMAT,
3471 : err.Format());
3472 0 : CommissioningStageComplete(err);
3473 0 : return;
3474 : }
3475 0 : break;
3476 : }
3477 0 : case CommissioningStage::kSendDACCertificateRequest: {
3478 0 : ChipLogProgress(Controller, "Sending request for DAC certificate");
3479 0 : CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kDAC, timeout);
3480 0 : if (err != CHIP_NO_ERROR)
3481 : {
3482 : // We won't get any async callbacks here, so just complete our stage.
3483 0 : ChipLogError(Controller, "Failed to send CertificateChainRequest command to get DAC: %" CHIP_ERROR_FORMAT,
3484 : err.Format());
3485 0 : CommissioningStageComplete(err);
3486 0 : return;
3487 : }
3488 0 : break;
3489 : }
3490 0 : case CommissioningStage::kSendAttestationRequest: {
3491 0 : ChipLogProgress(Controller, "Sending Attestation Request to the device.");
3492 0 : if (!params.GetAttestationNonce().HasValue())
3493 : {
3494 0 : ChipLogError(Controller, "No attestation nonce found");
3495 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3496 0 : return;
3497 : }
3498 0 : CHIP_ERROR err = SendAttestationRequestCommand(proxy, params.GetAttestationNonce().Value(), timeout);
3499 0 : if (err != CHIP_NO_ERROR)
3500 : {
3501 : // We won't get any async callbacks here, so just complete our stage.
3502 0 : ChipLogError(Controller, "Failed to send AttestationRequest command: %" CHIP_ERROR_FORMAT, err.Format());
3503 0 : CommissioningStageComplete(err);
3504 0 : return;
3505 : }
3506 0 : break;
3507 : }
3508 0 : case CommissioningStage::kAttestationVerification: {
3509 0 : ChipLogProgress(Controller, "Verifying Device Attestation information received from the device");
3510 0 : if (IsAttestationInformationMissing(params))
3511 : {
3512 0 : ChipLogError(Controller, "Missing attestation information");
3513 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3514 0 : return;
3515 : }
3516 :
3517 : DeviceAttestationVerifier::AttestationInfo info(
3518 0 : params.GetAttestationElements().Value(),
3519 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(),
3520 0 : params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(),
3521 0 : params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value());
3522 :
3523 0 : CHIP_ERROR err = ValidateAttestationInfo(info);
3524 0 : if (err != CHIP_NO_ERROR)
3525 : {
3526 0 : ChipLogError(Controller, "Error validating attestation information: %" CHIP_ERROR_FORMAT, err.Format());
3527 0 : CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION);
3528 0 : return;
3529 : }
3530 : }
3531 0 : break;
3532 0 : case CommissioningStage::kAttestationRevocationCheck: {
3533 0 : ChipLogProgress(Controller, "Verifying the device's DAC chain revocation status");
3534 0 : if (IsAttestationInformationMissing(params))
3535 : {
3536 0 : ChipLogError(Controller, "Missing attestation information");
3537 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3538 0 : return;
3539 : }
3540 :
3541 : DeviceAttestationVerifier::AttestationInfo info(
3542 0 : params.GetAttestationElements().Value(),
3543 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(),
3544 0 : params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(),
3545 0 : params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value());
3546 :
3547 0 : CHIP_ERROR err = CheckForRevokedDACChain(info);
3548 :
3549 0 : if (err != CHIP_NO_ERROR)
3550 : {
3551 0 : ChipLogError(Controller, "Error validating device's DAC chain revocation status: %" CHIP_ERROR_FORMAT, err.Format());
3552 0 : CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION);
3553 0 : return;
3554 : }
3555 : }
3556 0 : break;
3557 0 : case CommissioningStage::kJCMTrustVerification: {
3558 0 : CHIP_ERROR err = StartJCMTrustVerification(proxy);
3559 0 : if (err != CHIP_NO_ERROR)
3560 : {
3561 0 : ChipLogError(Controller, "Failed to start JCM Trust Verification: %" CHIP_ERROR_FORMAT, err.Format());
3562 0 : CommissioningStageComplete(err);
3563 0 : return;
3564 : }
3565 0 : break;
3566 : }
3567 :
3568 0 : case CommissioningStage::kSendOpCertSigningRequest: {
3569 0 : if (!params.GetCSRNonce().HasValue())
3570 : {
3571 0 : ChipLogError(Controller, "No CSR nonce found");
3572 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3573 0 : return;
3574 : }
3575 0 : CHIP_ERROR err = SendOperationalCertificateSigningRequestCommand(proxy, params.GetCSRNonce().Value(), timeout);
3576 0 : if (err != CHIP_NO_ERROR)
3577 : {
3578 : // We won't get any async callbacks here, so just complete our stage.
3579 0 : ChipLogError(Controller, "Failed to send CSR request: %" CHIP_ERROR_FORMAT, err.Format());
3580 0 : CommissioningStageComplete(err);
3581 0 : return;
3582 : }
3583 0 : break;
3584 : }
3585 0 : case CommissioningStage::kValidateCSR: {
3586 0 : if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetCSRNonce().HasValue())
3587 : {
3588 0 : ChipLogError(Controller, "Unable to validate CSR");
3589 0 : return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3590 : }
3591 : // This is non-blocking, so send the callback immediately.
3592 0 : CHIP_ERROR err = ValidateCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
3593 0 : params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
3594 0 : params.GetCSRNonce().Value());
3595 0 : if (err != CHIP_NO_ERROR)
3596 : {
3597 0 : ChipLogError(Controller, "Failed to validate CSR: %" CHIP_ERROR_FORMAT, err.Format());
3598 : }
3599 0 : CommissioningStageComplete(err);
3600 0 : return;
3601 : }
3602 : break;
3603 0 : case CommissioningStage::kGenerateNOCChain: {
3604 0 : if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
3605 0 : !params.GetCSRNonce().HasValue())
3606 : {
3607 0 : ChipLogError(Controller, "Unable to generate NOC chain parameters");
3608 0 : return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3609 : }
3610 0 : CHIP_ERROR err = ProcessCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
3611 0 : params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
3612 0 : params.GetPAI().Value(), params.GetCSRNonce().Value());
3613 0 : if (err != CHIP_NO_ERROR)
3614 : {
3615 0 : ChipLogError(Controller, "Failed to process Operational Certificate Signing Request (CSR): %" CHIP_ERROR_FORMAT,
3616 : err.Format());
3617 0 : CommissioningStageComplete(err);
3618 0 : return;
3619 : }
3620 : }
3621 0 : break;
3622 0 : case CommissioningStage::kSendTrustedRootCert: {
3623 0 : if (!params.GetRootCert().HasValue() || !params.GetNoc().HasValue())
3624 : {
3625 0 : ChipLogError(Controller, "No trusted root cert or NOC specified");
3626 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3627 0 : return;
3628 : }
3629 0 : CHIP_ERROR err = SendTrustedRootCertificate(proxy, params.GetRootCert().Value(), timeout);
3630 0 : if (err != CHIP_NO_ERROR)
3631 : {
3632 0 : ChipLogError(Controller, "Error sending trusted root certificate: %" CHIP_ERROR_FORMAT, err.Format());
3633 0 : CommissioningStageComplete(err);
3634 0 : return;
3635 : }
3636 :
3637 0 : err = proxy->SetPeerId(params.GetRootCert().Value(), params.GetNoc().Value());
3638 0 : if (err != CHIP_NO_ERROR)
3639 : {
3640 0 : ChipLogError(Controller, "Error setting peer id: %" CHIP_ERROR_FORMAT, err.Format());
3641 0 : CommissioningStageComplete(err);
3642 0 : return;
3643 : }
3644 0 : if (!IsOperationalNodeId(proxy->GetDeviceId()))
3645 : {
3646 0 : ChipLogError(Controller, "Given node ID is not an operational node ID");
3647 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3648 0 : return;
3649 : }
3650 : }
3651 0 : break;
3652 0 : case CommissioningStage::kSendNOC: {
3653 0 : if (!params.GetNoc().HasValue() || !params.GetIpk().HasValue() || !params.GetAdminSubject().HasValue())
3654 : {
3655 0 : ChipLogError(Controller, "AddNOC contents not specified");
3656 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3657 0 : return;
3658 : }
3659 0 : CHIP_ERROR err = SendOperationalCertificate(proxy, params.GetNoc().Value(), params.GetIcac(), params.GetIpk().Value(),
3660 0 : params.GetAdminSubject().Value(), timeout);
3661 0 : if (err != CHIP_NO_ERROR)
3662 : {
3663 : // We won't get any async callbacks here, so just complete our stage.
3664 0 : ChipLogError(Controller, "Error installing operational certificate with AddNOC: %" CHIP_ERROR_FORMAT, err.Format());
3665 0 : CommissioningStageComplete(err);
3666 0 : return;
3667 : }
3668 0 : break;
3669 : }
3670 0 : case CommissioningStage::kConfigureTrustedTimeSource: {
3671 0 : if (!params.GetTrustedTimeSource().HasValue())
3672 : {
3673 0 : ChipLogError(Controller, "ConfigureTrustedTimeSource stage called with no trusted time source data!");
3674 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3675 0 : return;
3676 : }
3677 0 : TimeSynchronization::Commands::SetTrustedTimeSource::Type request;
3678 0 : request.trustedTimeSource = params.GetTrustedTimeSource().Value();
3679 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
3680 0 : if (err != CHIP_NO_ERROR)
3681 : {
3682 : // We won't get any async callbacks here, so just complete our stage.
3683 0 : ChipLogError(Controller, "Failed to send SendTrustedTimeSource command: %" CHIP_ERROR_FORMAT, err.Format());
3684 0 : CommissioningStageComplete(err);
3685 0 : return;
3686 : }
3687 0 : break;
3688 : }
3689 0 : case CommissioningStage::kRequestWiFiCredentials: {
3690 0 : if (!mPairingDelegate)
3691 : {
3692 0 : ChipLogError(Controller, "Unable to request Wi-Fi credentials: no delegate available");
3693 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE);
3694 0 : return;
3695 : }
3696 :
3697 0 : CHIP_ERROR err = mPairingDelegate->WiFiCredentialsNeeded(endpoint);
3698 0 : CommissioningStageComplete(err);
3699 0 : return;
3700 : }
3701 0 : case CommissioningStage::kRequestThreadCredentials: {
3702 0 : if (!mPairingDelegate)
3703 : {
3704 0 : ChipLogError(Controller, "Unable to request Thread credentials: no delegate available");
3705 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE);
3706 0 : return;
3707 : }
3708 :
3709 0 : CHIP_ERROR err = mPairingDelegate->ThreadCredentialsNeeded(endpoint);
3710 0 : CommissioningStageComplete(err);
3711 0 : return;
3712 : }
3713 0 : case CommissioningStage::kWiFiNetworkSetup: {
3714 0 : if (!params.GetWiFiCredentials().HasValue())
3715 : {
3716 0 : ChipLogError(Controller, "No wifi credentials specified");
3717 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3718 0 : return;
3719 : }
3720 :
3721 0 : NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type request;
3722 0 : request.ssid = params.GetWiFiCredentials().Value().ssid;
3723 0 : request.credentials = params.GetWiFiCredentials().Value().credentials;
3724 0 : request.breadcrumb.Emplace(breadcrumb);
3725 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
3726 0 : if (err != CHIP_NO_ERROR)
3727 : {
3728 : // We won't get any async callbacks here, so just complete our stage.
3729 0 : ChipLogError(Controller, "Failed to send AddOrUpdateWiFiNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3730 0 : CommissioningStageComplete(err);
3731 0 : return;
3732 : }
3733 : }
3734 0 : break;
3735 0 : case CommissioningStage::kThreadNetworkSetup: {
3736 0 : if (!params.GetThreadOperationalDataset().HasValue())
3737 : {
3738 0 : ChipLogError(Controller, "No thread credentials specified");
3739 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3740 0 : return;
3741 : }
3742 0 : NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type request;
3743 0 : request.operationalDataset = params.GetThreadOperationalDataset().Value();
3744 0 : request.breadcrumb.Emplace(breadcrumb);
3745 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
3746 0 : if (err != CHIP_NO_ERROR)
3747 : {
3748 : // We won't get any async callbacks here, so just complete our stage.
3749 0 : ChipLogError(Controller, "Failed to send AddOrUpdateThreadNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3750 0 : CommissioningStageComplete(err);
3751 0 : return;
3752 : }
3753 : }
3754 0 : break;
3755 0 : case CommissioningStage::kFailsafeBeforeWiFiEnable:
3756 : FALLTHROUGH;
3757 : case CommissioningStage::kFailsafeBeforeThreadEnable:
3758 : // Before we try to do network enablement, make sure that our fail-safe
3759 : // is set far enough out that we can later try to do operational
3760 : // discovery without it timing out.
3761 0 : ExtendFailsafeBeforeNetworkEnable(proxy, params, step);
3762 0 : break;
3763 0 : case CommissioningStage::kWiFiNetworkEnable: {
3764 0 : if (!params.GetWiFiCredentials().HasValue())
3765 : {
3766 0 : ChipLogError(Controller, "No wifi credentials specified");
3767 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3768 0 : return;
3769 : }
3770 0 : NetworkCommissioning::Commands::ConnectNetwork::Type request;
3771 0 : request.networkID = params.GetWiFiCredentials().Value().ssid;
3772 0 : request.breadcrumb.Emplace(breadcrumb);
3773 :
3774 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3775 0 : ChipLogProgress(Controller, "SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%s",
3776 : params.GetSupportsConcurrentConnection().HasValue()
3777 : ? (params.GetSupportsConcurrentConnection().Value() ? "true" : "false")
3778 : : "missing");
3779 0 : err = SendCommissioningCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
3780 :
3781 0 : if (err != CHIP_NO_ERROR)
3782 : {
3783 : // We won't get any async callbacks here, so just complete our stage.
3784 0 : ChipLogError(Controller, "Failed to send WiFi ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3785 0 : CommissioningStageComplete(err);
3786 0 : return;
3787 : }
3788 : }
3789 0 : break;
3790 0 : case CommissioningStage::kThreadNetworkEnable: {
3791 0 : ByteSpan extendedPanId;
3792 0 : chip::Thread::OperationalDataset operationalDataset;
3793 0 : if (!params.GetThreadOperationalDataset().HasValue() ||
3794 0 : operationalDataset.Init(params.GetThreadOperationalDataset().Value()) != CHIP_NO_ERROR ||
3795 0 : operationalDataset.GetExtendedPanIdAsByteSpan(extendedPanId) != CHIP_NO_ERROR)
3796 : {
3797 0 : ChipLogError(Controller, "Invalid Thread operational dataset configured at commissioner!");
3798 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3799 0 : return;
3800 : }
3801 0 : NetworkCommissioning::Commands::ConnectNetwork::Type request;
3802 0 : request.networkID = extendedPanId;
3803 0 : request.breadcrumb.Emplace(breadcrumb);
3804 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
3805 0 : if (err != CHIP_NO_ERROR)
3806 : {
3807 : // We won't get any async callbacks here, so just complete our stage.
3808 0 : ChipLogError(Controller, "Failed to send Thread ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3809 0 : CommissioningStageComplete(err);
3810 0 : return;
3811 : }
3812 : }
3813 0 : break;
3814 0 : case CommissioningStage::kICDGetRegistrationInfo: {
3815 0 : GetPairingDelegate()->OnICDRegistrationInfoRequired();
3816 0 : return;
3817 : }
3818 : break;
3819 0 : case CommissioningStage::kICDRegistration: {
3820 0 : IcdManagement::Commands::RegisterClient::Type request;
3821 :
3822 0 : if (!(params.GetICDCheckInNodeId().HasValue() && params.GetICDMonitoredSubject().HasValue() &&
3823 0 : params.GetICDSymmetricKey().HasValue()))
3824 : {
3825 0 : ChipLogError(Controller, "No ICD Registration information provided!");
3826 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE);
3827 0 : return;
3828 : }
3829 :
3830 0 : request.checkInNodeID = params.GetICDCheckInNodeId().Value();
3831 0 : request.monitoredSubject = params.GetICDMonitoredSubject().Value();
3832 0 : request.key = params.GetICDSymmetricKey().Value();
3833 :
3834 : CHIP_ERROR err =
3835 0 : SendCommissioningCommand(proxy, request, OnICDManagementRegisterClientResponse, OnBasicFailure, endpoint, timeout);
3836 0 : if (err != CHIP_NO_ERROR)
3837 : {
3838 : // We won't get any async callbacks here, so just complete our stage.
3839 0 : ChipLogError(Controller, "Failed to send IcdManagement.RegisterClient command: %" CHIP_ERROR_FORMAT, err.Format());
3840 0 : CommissioningStageComplete(err);
3841 0 : return;
3842 : }
3843 : }
3844 0 : break;
3845 0 : case CommissioningStage::kEvictPreviousCaseSessions: {
3846 0 : auto scopedPeerId = GetPeerScopedId(proxy->GetDeviceId());
3847 :
3848 : // If we ever had a commissioned device with this node ID before, we may
3849 : // have stale sessions to it. Make sure we don't re-use any of those,
3850 : // because clearly they are not related to this new device we are
3851 : // commissioning. We only care about sessions we might reuse, so just
3852 : // clearing the ones associated with our fabric index is good enough and
3853 : // we don't need to worry about ExpireAllSessionsOnLogicalFabric.
3854 0 : mSystemState->SessionMgr()->ExpireAllSessions(scopedPeerId);
3855 : #if CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
3856 : Transport::Type type = proxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress().GetTransportType();
3857 : // cache address if we are connected over TCP or UDP
3858 : if (type == Transport::Type::kTcp || type == Transport::Type::kUdp)
3859 : {
3860 : // Store the address we are using for PASE as a fallback for operational discovery
3861 : ResolveResult result;
3862 : result.address = proxy->GetSecureSession().Value()->AsSecureSession()->GetPeerAddress();
3863 : result.mrpRemoteConfig = proxy->GetSecureSession().Value()->GetRemoteMRPConfig();
3864 : // Note: supportsTcpClient and supportsTcpServer are device capabilities from DNS-SD TXT records,
3865 : // not derivable from the transport type. They remain false (default) here.
3866 : // TODO: Consider passing these through RendezvousParameters if available from SetUpCodePairer.
3867 : mFallbackOperationalResolveResult.SetValue(result);
3868 : }
3869 : #endif // CHIP_CONFIG_ENABLE_ADDRESS_RESOLVE_FALLBACK
3870 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3871 0 : return;
3872 : }
3873 0 : case CommissioningStage::kFindOperationalForStayActive:
3874 : case CommissioningStage::kFindOperationalForCommissioningComplete: {
3875 : // If there is an error, CommissioningStageComplete will be called from OnDeviceConnectionFailureFn.
3876 0 : auto scopedPeerId = GetPeerScopedId(proxy->GetDeviceId());
3877 : MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioningOperationalSetup);
3878 0 : mSystemState->CASESessionMgr()->FindOrEstablishSession(
3879 : scopedPeerId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback,
3880 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
3881 : /* attemptCount = */ 3, &mOnDeviceConnectionRetryCallback,
3882 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
3883 0 : TransportPayloadCapability::kMRPPayload, mFallbackOperationalResolveResult);
3884 : }
3885 0 : break;
3886 0 : case CommissioningStage::kPrimaryOperationalNetworkFailed: {
3887 : // nothing to do. This stage indicates that the primary operational network failed and the network config should be
3888 : // removed later.
3889 0 : break;
3890 : }
3891 0 : case CommissioningStage::kRemoveWiFiNetworkConfig: {
3892 0 : NetworkCommissioning::Commands::RemoveNetwork::Type request;
3893 0 : request.networkID = params.GetWiFiCredentials().Value().ssid;
3894 0 : request.breadcrumb.Emplace(breadcrumb);
3895 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
3896 0 : if (err != CHIP_NO_ERROR)
3897 : {
3898 : // We won't get any async callbacks here, so just complete our stage.
3899 0 : ChipLogError(Controller, "Failed to send RemoveNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3900 0 : CommissioningStageComplete(err);
3901 0 : return;
3902 : }
3903 0 : break;
3904 : }
3905 0 : case CommissioningStage::kRemoveThreadNetworkConfig: {
3906 0 : ByteSpan extendedPanId;
3907 0 : chip::Thread::OperationalDataset operationalDataset;
3908 0 : if (!params.GetThreadOperationalDataset().HasValue() ||
3909 0 : operationalDataset.Init(params.GetThreadOperationalDataset().Value()) != CHIP_NO_ERROR ||
3910 0 : operationalDataset.GetExtendedPanIdAsByteSpan(extendedPanId) != CHIP_NO_ERROR)
3911 : {
3912 0 : ChipLogError(Controller, "Invalid Thread operational dataset configured at commissioner!");
3913 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3914 0 : return;
3915 : }
3916 0 : NetworkCommissioning::Commands::RemoveNetwork::Type request;
3917 0 : request.networkID = extendedPanId;
3918 0 : request.breadcrumb.Emplace(breadcrumb);
3919 0 : CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
3920 0 : if (err != CHIP_NO_ERROR)
3921 : {
3922 : // We won't get any async callbacks here, so just complete our stage.
3923 0 : ChipLogError(Controller, "Failed to send RemoveNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3924 0 : CommissioningStageComplete(err);
3925 0 : return;
3926 : }
3927 0 : break;
3928 : }
3929 0 : case CommissioningStage::kICDSendStayActive: {
3930 0 : if (!(params.GetICDStayActiveDurationMsec().HasValue()))
3931 : {
3932 0 : ChipLogProgress(Controller, "Skipping kICDSendStayActive");
3933 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3934 0 : return;
3935 : }
3936 :
3937 : // StayActive Command happens over CASE Connection
3938 0 : IcdManagement::Commands::StayActiveRequest::Type request;
3939 0 : request.stayActiveDuration = params.GetICDStayActiveDurationMsec().Value();
3940 0 : ChipLogError(Controller, "Send ICD StayActive with Duration %u", request.stayActiveDuration);
3941 : CHIP_ERROR err =
3942 0 : SendCommissioningCommand(proxy, request, OnICDManagementStayActiveResponse, OnBasicFailure, endpoint, timeout);
3943 0 : if (err != CHIP_NO_ERROR)
3944 : {
3945 : // We won't get any async callbacks here, so just complete our stage.
3946 0 : ChipLogError(Controller, "Failed to send IcdManagement.StayActive command: %" CHIP_ERROR_FORMAT, err.Format());
3947 0 : CommissioningStageComplete(err);
3948 0 : return;
3949 : }
3950 : }
3951 0 : break;
3952 0 : case CommissioningStage::kSendComplete: {
3953 : // CommissioningComplete command happens over the CASE connection.
3954 : GeneralCommissioning::Commands::CommissioningComplete::Type request;
3955 : CHIP_ERROR err =
3956 0 : SendCommissioningCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout);
3957 0 : if (err != CHIP_NO_ERROR)
3958 : {
3959 : // We won't get any async callbacks here, so just complete our stage.
3960 0 : ChipLogError(Controller, "Failed to send CommissioningComplete command: %" CHIP_ERROR_FORMAT, err.Format());
3961 0 : CommissioningStageComplete(err);
3962 0 : return;
3963 : }
3964 : }
3965 0 : break;
3966 : #if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
3967 : case CommissioningStage::kUnpoweredPhaseComplete:
3968 : ChipLogProgress(Controller, "Completed unpowered commissioning phase, marking commissioning as complete");
3969 : CommissioningStageComplete(CHIP_NO_ERROR);
3970 : break;
3971 : #endif
3972 0 : case CommissioningStage::kCleanup:
3973 0 : CleanupCommissioning(proxy, proxy->GetDeviceId(), params.GetCompletionStatus());
3974 0 : break;
3975 0 : case CommissioningStage::kError:
3976 0 : mCommissioningStage = CommissioningStage::kSecurePairing;
3977 0 : break;
3978 0 : case CommissioningStage::kSecurePairing:
3979 0 : break;
3980 : }
3981 : }
3982 :
3983 0 : void DeviceCommissioner::ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params,
3984 : CommissioningStage step)
3985 : {
3986 0 : auto * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
3987 0 : if (device != commissioneeDevice)
3988 : {
3989 : // Not a commissionee device; just return.
3990 0 : ChipLogError(Controller, "Trying to extend fail-safe for an unknown commissionee with device id " ChipLogFormatX64,
3991 : ChipLogValueX64(device->GetDeviceId()));
3992 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE, CommissioningDelegate::CommissioningReport());
3993 0 : return;
3994 : }
3995 :
3996 : // Try to make sure we have at least enough time for our expected
3997 : // commissioning bits plus the MRP retries for a Sigma1.
3998 0 : uint16_t failSafeTimeoutSecs = params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout);
3999 0 : auto sigma1Timeout = CASESession::ComputeSigma1ResponseTimeout(commissioneeDevice->GetPairing().GetRemoteMRPConfig());
4000 0 : uint16_t sigma1TimeoutSecs = std::chrono::duration_cast<System::Clock::Seconds16>(sigma1Timeout).count();
4001 0 : if (UINT16_MAX - failSafeTimeoutSecs < sigma1TimeoutSecs)
4002 : {
4003 0 : failSafeTimeoutSecs = UINT16_MAX;
4004 : }
4005 : else
4006 : {
4007 0 : failSafeTimeoutSecs = static_cast<uint16_t>(failSafeTimeoutSecs + sigma1TimeoutSecs);
4008 : }
4009 :
4010 0 : if (!ExtendArmFailSafeInternal(commissioneeDevice, step, failSafeTimeoutSecs, MakeOptional(kMinimumCommissioningStepTimeout),
4011 : OnArmFailSafe, OnBasicFailure, /* fireAndForget = */ false))
4012 : {
4013 : // A false return is fine; we don't want to make the fail-safe shorter here.
4014 0 : CommissioningStageComplete(CHIP_NO_ERROR, CommissioningDelegate::CommissioningReport());
4015 : }
4016 : }
4017 :
4018 0 : bool DeviceCommissioner::IsAttestationInformationMissing(const CommissioningParameters & params)
4019 : {
4020 0 : if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
4021 0 : !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
4022 0 : !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
4023 : {
4024 0 : return true;
4025 : }
4026 :
4027 0 : return false;
4028 : }
4029 :
4030 0 : CHIP_ERROR DeviceController::GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const
4031 : {
4032 0 : const auto * fabricInfo = GetFabricInfo();
4033 0 : VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
4034 0 : return fabricInfo->GetCompressedFabricIdBytes(outBytes);
4035 : }
4036 :
4037 0 : CHIP_ERROR DeviceController::GetRootPublicKey(Crypto::P256PublicKey & outRootPublicKey) const
4038 : {
4039 0 : const auto * fabricTable = GetFabricTable();
4040 0 : VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INCORRECT_STATE);
4041 0 : return fabricTable->FetchRootPubkey(mFabricIndex, outRootPublicKey);
4042 : }
4043 :
4044 0 : bool DeviceCommissioner::HasValidCommissioningMode(const Dnssd::CommissionNodeData & nodeData)
4045 : {
4046 0 : if (nodeData.commissioningMode == to_underlying(Dnssd::CommissioningMode::kDisabled))
4047 : {
4048 0 : ChipLogProgress(Controller, "Discovered device does not have an open commissioning window.");
4049 0 : return false;
4050 : }
4051 0 : return true;
4052 : }
4053 :
4054 : } // namespace Controller
4055 : } // namespace chip
|