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