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