Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2022 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 : #ifndef __STDC_LIMIT_MACROS
29 : #define __STDC_LIMIT_MACROS
30 : #endif
31 : #ifndef __STDC_FORMAT_MACROS
32 : #define __STDC_FORMAT_MACROS
33 : #endif
34 :
35 : // module header, comes first
36 : #include <controller/CHIPDeviceController.h>
37 :
38 : #include <app-common/zap-generated/ids/Attributes.h>
39 : #include <app-common/zap-generated/ids/Clusters.h>
40 :
41 : #include <app/server/Dnssd.h>
42 :
43 : #include <app/InteractionModelEngine.h>
44 : #include <app/OperationalSessionSetup.h>
45 : #include <controller/CurrentFabricRemover.h>
46 : #include <credentials/CHIPCert.h>
47 : #include <credentials/DeviceAttestationCredsProvider.h>
48 : #include <crypto/CHIPCryptoPAL.h>
49 : #include <lib/core/CHIPCore.h>
50 : #include <lib/core/CHIPEncoding.h>
51 : #include <lib/core/CHIPSafeCasts.h>
52 : #include <lib/core/ErrorStr.h>
53 : #include <lib/core/NodeId.h>
54 : #include <lib/support/Base64.h>
55 : #include <lib/support/CHIPArgParser.hpp>
56 : #include <lib/support/CHIPMem.h>
57 : #include <lib/support/CodeUtils.h>
58 : #include <lib/support/PersistentStorageMacros.h>
59 : #include <lib/support/SafeInt.h>
60 : #include <lib/support/ScopedBuffer.h>
61 : #include <lib/support/ThreadOperationalDataset.h>
62 : #include <lib/support/TimeUtils.h>
63 : #include <lib/support/logging/CHIPLogging.h>
64 : #include <messaging/ExchangeContext.h>
65 : #include <platform/LockTracker.h>
66 : #include <protocols/secure_channel/MessageCounterManager.h>
67 : #include <setup_payload/QRCodeSetupPayloadParser.h>
68 : #include <tracing/macros.h>
69 :
70 : #if CONFIG_NETWORK_LAYER_BLE
71 : #include <ble/BleLayer.h>
72 : #include <transport/raw/BLE.h>
73 : #endif
74 :
75 : #include <errno.h>
76 : #include <inttypes.h>
77 : #include <memory>
78 : #include <stdint.h>
79 : #include <stdlib.h>
80 : #include <time.h>
81 :
82 : using namespace chip::Inet;
83 : using namespace chip::System;
84 : using namespace chip::Transport;
85 : using namespace chip::Credentials;
86 : using namespace chip::app::Clusters;
87 :
88 : namespace chip {
89 : namespace Controller {
90 :
91 : using namespace chip::Encoding;
92 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
93 : using namespace chip::Protocols::UserDirectedCommissioning;
94 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
95 :
96 0 : DeviceController::DeviceController()
97 : {
98 0 : mState = State::NotInitialized;
99 0 : }
100 :
101 0 : CHIP_ERROR DeviceController::Init(ControllerInitParams params)
102 : {
103 0 : assertChipStackLockedByCurrentThread();
104 :
105 0 : VerifyOrReturnError(mState == State::NotInitialized, CHIP_ERROR_INCORRECT_STATE);
106 0 : VerifyOrReturnError(params.systemState != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
107 :
108 0 : VerifyOrReturnError(params.systemState->SystemLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
109 0 : VerifyOrReturnError(params.systemState->UDPEndPointManager() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
110 :
111 : #if CONFIG_NETWORK_LAYER_BLE
112 0 : VerifyOrReturnError(params.systemState->BleLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
113 : #endif
114 :
115 0 : VerifyOrReturnError(params.systemState->TransportMgr() != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
116 :
117 0 : ReturnErrorOnFailure(mDNSResolver.Init(params.systemState->UDPEndPointManager()));
118 0 : mDNSResolver.SetCommissioningDelegate(this);
119 0 : RegisterDeviceDiscoveryDelegate(params.deviceDiscoveryDelegate);
120 :
121 0 : VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
122 0 : mOperationalCredentialsDelegate = params.operationalCredentialsDelegate;
123 :
124 0 : mVendorId = params.controllerVendorId;
125 0 : if (params.operationalKeypair != nullptr || !params.controllerNOC.empty() || !params.controllerRCAC.empty())
126 : {
127 0 : ReturnErrorOnFailure(InitControllerNOCChain(params));
128 : }
129 :
130 0 : mSystemState = params.systemState->Retain();
131 0 : mState = State::Initialized;
132 :
133 0 : mRemoveFromFabricTableOnShutdown = params.removeFromFabricTableOnShutdown;
134 :
135 0 : if (GetFabricIndex() != kUndefinedFabricIndex)
136 : {
137 0 : ChipLogProgress(Controller,
138 : "Joined the fabric at index %d. Fabric ID is 0x" ChipLogFormatX64
139 : " (Compressed Fabric ID: " ChipLogFormatX64 ")",
140 : GetFabricIndex(), ChipLogValueX64(GetFabricId()), ChipLogValueX64(GetCompressedFabricId()));
141 : }
142 :
143 0 : return CHIP_NO_ERROR;
144 : }
145 :
146 0 : CHIP_ERROR DeviceController::InitControllerNOCChain(const ControllerInitParams & params)
147 : {
148 0 : FabricInfo newFabric;
149 0 : constexpr uint32_t chipCertAllocatedLen = kMaxCHIPCertLength;
150 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> rcacBuf;
151 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
152 0 : chip::Platform::ScopedMemoryBuffer<uint8_t> nocBuf;
153 0 : Credentials::P256PublicKeySpan rootPublicKeySpan;
154 : FabricId fabricId;
155 : NodeId nodeId;
156 0 : bool hasExternallyOwnedKeypair = false;
157 0 : Crypto::P256Keypair * externalOperationalKeypair = nullptr;
158 0 : VendorId newFabricVendorId = params.controllerVendorId;
159 :
160 : // There are three possibilities here in terms of what happens with our
161 : // operational key:
162 : // 1) We have an externally owned operational keypair.
163 : // 2) We have an operational keypair that the fabric table should clone via
164 : // serialize/deserialize.
165 : // 3) We have no keypair at all, and the fabric table has been initialized
166 : // with a key store.
167 0 : if (params.operationalKeypair != nullptr)
168 : {
169 0 : hasExternallyOwnedKeypair = params.hasExternallyOwnedOperationalKeypair;
170 0 : externalOperationalKeypair = params.operationalKeypair;
171 : }
172 :
173 0 : ReturnErrorCodeIf(!rcacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
174 0 : ReturnErrorCodeIf(!icacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
175 0 : ReturnErrorCodeIf(!nocBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
176 :
177 0 : MutableByteSpan rcacSpan(rcacBuf.Get(), chipCertAllocatedLen);
178 :
179 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerRCAC, rcacSpan));
180 0 : ReturnErrorOnFailure(Credentials::ExtractPublicKeyFromChipCert(rcacSpan, rootPublicKeySpan));
181 0 : Crypto::P256PublicKey rootPublicKey{ rootPublicKeySpan };
182 :
183 0 : MutableByteSpan icacSpan;
184 0 : if (params.controllerICAC.empty())
185 : {
186 0 : ChipLogProgress(Controller, "Intermediate CA is not needed");
187 : }
188 : else
189 : {
190 0 : icacSpan = MutableByteSpan(icacBuf.Get(), chipCertAllocatedLen);
191 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerICAC, icacSpan));
192 : }
193 :
194 0 : MutableByteSpan nocSpan = MutableByteSpan(nocBuf.Get(), chipCertAllocatedLen);
195 :
196 0 : ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerNOC, nocSpan));
197 0 : ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(nocSpan, &nodeId, &fabricId));
198 :
199 0 : auto * fabricTable = params.systemState->Fabrics();
200 0 : const FabricInfo * fabricInfo = nullptr;
201 :
202 : //
203 : // When multiple controllers are permitted on the same fabric, we need to find fabrics with
204 : // nodeId as an extra discriminant since we can have multiple FabricInfo objects that all
205 : // collide on the same fabric. Not doing so may result in a match with an existing FabricInfo
206 : // instance that matches the fabric in the provided NOC but is associated with a different NodeId
207 : // that is already in use by another active controller instance. That will effectively cause it
208 : // to change its identity inadvertently, which is not acceptable.
209 : //
210 : // TODO: Figure out how to clean up unreclaimed FabricInfos restored from persistent
211 : // storage that are not in use by active DeviceController instances. Also, figure out
212 : // how to reclaim FabricInfo slots when a DeviceController instance is deleted.
213 : //
214 0 : if (params.permitMultiControllerFabrics)
215 : {
216 0 : fabricInfo = fabricTable->FindIdentity(rootPublicKey, fabricId, nodeId);
217 : }
218 : else
219 : {
220 0 : fabricInfo = fabricTable->FindFabric(rootPublicKey, fabricId);
221 : }
222 :
223 0 : bool fabricFoundInTable = (fabricInfo != nullptr);
224 :
225 0 : FabricIndex fabricIndex = fabricFoundInTable ? fabricInfo->GetFabricIndex() : kUndefinedFabricIndex;
226 :
227 0 : CHIP_ERROR err = CHIP_NO_ERROR;
228 :
229 0 : auto advertiseOperational =
230 0 : params.enableServerInteractions ? FabricTable::AdvertiseIdentity::Yes : FabricTable::AdvertiseIdentity::No;
231 :
232 : //
233 : // We permit colliding fabrics when multiple controllers are present on the same logical fabric
234 : // since each controller is associated with a unique FabricInfo 'identity' object and consequently,
235 : // a unique FabricIndex.
236 : //
237 : // This sets a flag that will be cleared automatically when the fabric is committed/reverted later
238 : // in this function.
239 : //
240 0 : if (params.permitMultiControllerFabrics)
241 : {
242 0 : fabricTable->PermitCollidingFabrics();
243 : }
244 :
245 : // We have 4 cases to handle legacy usage of direct operational key injection
246 0 : if (externalOperationalKeypair)
247 : {
248 : // Cases 1 and 2: Injected operational keys
249 :
250 : // CASE 1: Fabric update with injected key
251 0 : if (fabricFoundInTable)
252 : {
253 0 : err = fabricTable->UpdatePendingFabricWithProvidedOpKey(fabricIndex, nocSpan, icacSpan, externalOperationalKeypair,
254 : hasExternallyOwnedKeypair, advertiseOperational);
255 : }
256 : else
257 : // CASE 2: New fabric with injected key
258 : {
259 0 : err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
260 0 : if (err == CHIP_NO_ERROR)
261 : {
262 0 : err = fabricTable->AddNewPendingFabricWithProvidedOpKey(nocSpan, icacSpan, newFabricVendorId,
263 : externalOperationalKeypair, hasExternallyOwnedKeypair,
264 : &fabricIndex, advertiseOperational);
265 : }
266 : }
267 : }
268 : else
269 : {
270 : // Cases 3 and 4: OperationalKeystore has the keys
271 :
272 : // CASE 3: Fabric update with operational keystore
273 0 : if (fabricFoundInTable)
274 : {
275 0 : VerifyOrReturnError(fabricTable->HasOperationalKeyForFabric(fabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
276 :
277 0 : err = fabricTable->UpdatePendingFabricWithOperationalKeystore(fabricIndex, nocSpan, icacSpan, advertiseOperational);
278 : }
279 : else
280 : // CASE 4: New fabric with operational keystore
281 : {
282 0 : err = fabricTable->AddNewPendingTrustedRootCert(rcacSpan);
283 0 : if (err == CHIP_NO_ERROR)
284 : {
285 0 : err = fabricTable->AddNewPendingFabricWithOperationalKeystore(nocSpan, icacSpan, newFabricVendorId, &fabricIndex,
286 : advertiseOperational);
287 : }
288 :
289 0 : if (err == CHIP_NO_ERROR)
290 : {
291 : // Now that we know our planned fabric index, verify that the
292 : // keystore has a key for it.
293 0 : if (!fabricTable->HasOperationalKeyForFabric(fabricIndex))
294 : {
295 0 : err = CHIP_ERROR_KEY_NOT_FOUND;
296 : }
297 : }
298 : }
299 : }
300 :
301 : // Commit after setup, error-out on failure.
302 0 : if (err == CHIP_NO_ERROR)
303 : {
304 : // No need to revert on error: CommitPendingFabricData reverts internally on *any* error.
305 0 : err = fabricTable->CommitPendingFabricData();
306 : }
307 : else
308 : {
309 0 : fabricTable->RevertPendingFabricData();
310 : }
311 :
312 0 : ReturnErrorOnFailure(err);
313 0 : VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
314 :
315 0 : mFabricIndex = fabricIndex;
316 :
317 0 : return CHIP_NO_ERROR;
318 0 : }
319 :
320 0 : void DeviceController::Shutdown()
321 : {
322 0 : assertChipStackLockedByCurrentThread();
323 :
324 0 : VerifyOrReturn(mState != State::NotInitialized);
325 :
326 0 : ChipLogDetail(Controller, "Shutting down the controller");
327 :
328 0 : mState = State::NotInitialized;
329 :
330 0 : if (mFabricIndex != kUndefinedFabricIndex)
331 : {
332 : // Shut down any subscription clients for this fabric.
333 0 : app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(mFabricIndex);
334 :
335 : // Shut down any ongoing CASE session activity we have. We're going to
336 : // assume that all sessions for our fabric belong to us here.
337 0 : mSystemState->CASESessionMgr()->ReleaseSessionsForFabric(mFabricIndex);
338 :
339 : // TODO: The CASE session manager does not shut down existing CASE
340 : // sessions. It just shuts down any ongoing CASE session establishment
341 : // we're in the middle of as initiator. Maybe it should shut down
342 : // existing sessions too?
343 0 : mSystemState->SessionMgr()->ExpireAllSessionsForFabric(mFabricIndex);
344 :
345 0 : if (mRemoveFromFabricTableOnShutdown)
346 : {
347 0 : FabricTable * fabricTable = mSystemState->Fabrics();
348 0 : if (fabricTable != nullptr)
349 : {
350 0 : fabricTable->Forget(mFabricIndex);
351 : }
352 : }
353 : }
354 :
355 0 : mSystemState->Release();
356 0 : mSystemState = nullptr;
357 :
358 0 : mDNSResolver.Shutdown();
359 0 : mDeviceDiscoveryDelegate = nullptr;
360 : }
361 :
362 0 : CHIP_ERROR DeviceController::GetPeerAddressAndPort(NodeId peerId, Inet::IPAddress & addr, uint16_t & port)
363 : {
364 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
365 0 : Transport::PeerAddress peerAddr;
366 0 : ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(peerId), peerAddr));
367 0 : addr = peerAddr.GetIPAddress();
368 0 : port = peerAddr.GetPort();
369 0 : return CHIP_NO_ERROR;
370 : }
371 :
372 0 : CHIP_ERROR DeviceController::GetPeerAddress(NodeId nodeId, Transport::PeerAddress & addr)
373 : {
374 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
375 0 : ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(GetPeerScopedId(nodeId), addr));
376 :
377 0 : return CHIP_NO_ERROR;
378 : }
379 :
380 0 : CHIP_ERROR DeviceController::ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt,
381 : Spake2pVerifier & outVerifier)
382 : {
383 0 : ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(outVerifier, iterations, salt, /* useRandomPIN= */ false, setupPincode));
384 :
385 0 : return CHIP_NO_ERROR;
386 : }
387 :
388 0 : ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams()
389 : {
390 : return ControllerDeviceInitParams{
391 0 : .sessionManager = mSystemState->SessionMgr(),
392 0 : .exchangeMgr = mSystemState->ExchangeMgr(),
393 0 : };
394 : }
395 :
396 0 : DeviceCommissioner::DeviceCommissioner() :
397 0 : mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this),
398 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
399 0 : mOnDeviceConnectionRetryCallback(OnDeviceConnectionRetryFn, this),
400 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
401 0 : mDeviceAttestationInformationVerificationCallback(OnDeviceAttestationInformationVerification, this),
402 0 : mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this)
403 : {
404 0 : mPairingDelegate = nullptr;
405 0 : mDeviceBeingCommissioned = nullptr;
406 0 : mDeviceInPASEEstablishment = nullptr;
407 0 : }
408 :
409 0 : CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params)
410 : {
411 0 : ReturnErrorOnFailure(DeviceController::Init(params));
412 :
413 0 : mPairingDelegate = params.pairingDelegate;
414 :
415 : // Configure device attestation validation
416 0 : mDeviceAttestationVerifier = params.deviceAttestationVerifier;
417 0 : if (mDeviceAttestationVerifier == nullptr)
418 : {
419 0 : mDeviceAttestationVerifier = Credentials::GetDeviceAttestationVerifier();
420 0 : if (mDeviceAttestationVerifier == nullptr)
421 : {
422 0 : ChipLogError(Controller,
423 : "Missing DeviceAttestationVerifier configuration at DeviceCommissioner init and none set with "
424 : "Credentials::SetDeviceAttestationVerifier()!");
425 0 : return CHIP_ERROR_INVALID_ARGUMENT;
426 : }
427 :
428 : // We fell back on a default from singleton accessor.
429 0 : ChipLogProgress(Controller,
430 : "*** Missing DeviceAttestationVerifier configuration at DeviceCommissioner init: using global default, "
431 : "consider passing one in CommissionerInitParams.");
432 : }
433 :
434 0 : if (params.defaultCommissioner != nullptr)
435 : {
436 0 : mDefaultCommissioner = params.defaultCommissioner;
437 : }
438 : else
439 : {
440 0 : mDefaultCommissioner = &mAutoCommissioner;
441 : }
442 :
443 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
444 : mUdcTransportMgr = chip::Platform::New<UdcTransportMgr>();
445 : ReturnErrorOnFailure(mUdcTransportMgr->Init(Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
446 : .SetAddressType(Inet::IPAddressType::kIPv6)
447 : .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
448 : #if INET_CONFIG_ENABLE_IPV4
449 : ,
450 : Transport::UdpListenParameters(mSystemState->UDPEndPointManager())
451 : .SetAddressType(Inet::IPAddressType::kIPv4)
452 : .SetListenPort(static_cast<uint16_t>(mUdcListenPort))
453 : #endif // INET_CONFIG_ENABLE_IPV4
454 : ));
455 :
456 : mUdcServer = chip::Platform::New<UserDirectedCommissioningServer>();
457 : mUdcTransportMgr->SetSessionManager(mUdcServer);
458 : mUdcServer->SetTransportManager(mUdcTransportMgr);
459 :
460 : mUdcServer->SetInstanceNameResolver(this);
461 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
462 :
463 0 : mSetUpCodePairer.SetSystemLayer(mSystemState->SystemLayer());
464 : #if CONFIG_NETWORK_LAYER_BLE
465 0 : mSetUpCodePairer.SetBleLayer(mSystemState->BleLayer());
466 : #endif // CONFIG_NETWORK_LAYER_BLE
467 :
468 0 : return CHIP_NO_ERROR;
469 : }
470 :
471 0 : void DeviceCommissioner::Shutdown()
472 : {
473 0 : VerifyOrReturn(mState != State::NotInitialized);
474 :
475 0 : ChipLogDetail(Controller, "Shutting down the commissioner");
476 :
477 0 : mSetUpCodePairer.StopPairing();
478 :
479 : // Check to see if pairing in progress before shutting down
480 0 : CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
481 0 : if (device != nullptr && device->IsSessionSetupInProgress())
482 : {
483 0 : ChipLogDetail(Controller, "Setup in progress, stopping setup before shutting down");
484 0 : OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED);
485 : }
486 : // TODO: If we have a commissioning step in progress, is there a way to cancel that callback?
487 :
488 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
489 : if (mUdcTransportMgr != nullptr)
490 : {
491 : chip::Platform::Delete(mUdcTransportMgr);
492 : mUdcTransportMgr = nullptr;
493 : }
494 : if (mUdcServer != nullptr)
495 : {
496 : mUdcServer->SetInstanceNameResolver(nullptr);
497 : chip::Platform::Delete(mUdcServer);
498 : mUdcServer = nullptr;
499 : }
500 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
501 :
502 : // Release everything from the commissionee device pool here.
503 : // Make sure to use ReleaseCommissioneeDevice so we don't keep dangling
504 : // pointers to the device objects.
505 0 : mCommissioneeDevicePool.ForEachActiveObject([this](auto * commissioneeDevice) {
506 0 : ReleaseCommissioneeDevice(commissioneeDevice);
507 0 : return Loop::Continue;
508 : });
509 :
510 0 : DeviceController::Shutdown();
511 : }
512 :
513 0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(NodeId id)
514 : {
515 : MATTER_TRACE_SCOPE("FindCommissioneeDevice", "DeviceCommissioner");
516 0 : CommissioneeDeviceProxy * foundDevice = nullptr;
517 0 : mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
518 0 : if (deviceProxy->GetDeviceId() == id)
519 : {
520 0 : foundDevice = deviceProxy;
521 0 : return Loop::Break;
522 : }
523 0 : return Loop::Continue;
524 : });
525 :
526 0 : return foundDevice;
527 : }
528 :
529 0 : CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(const Transport::PeerAddress & peerAddress)
530 : {
531 0 : CommissioneeDeviceProxy * foundDevice = nullptr;
532 0 : mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) {
533 0 : if (deviceProxy->GetPeerAddress() == peerAddress)
534 : {
535 0 : foundDevice = deviceProxy;
536 0 : return Loop::Break;
537 : }
538 0 : return Loop::Continue;
539 : });
540 :
541 0 : return foundDevice;
542 : }
543 :
544 0 : void DeviceCommissioner::ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device)
545 : {
546 : #if CONFIG_NETWORK_LAYER_BLE
547 0 : if (mSystemState->BleLayer() != nullptr && device->GetDeviceTransportType() == Transport::Type::kBle)
548 : {
549 : // We only support one BLE connection, so if this is BLE, close it
550 0 : ChipLogProgress(Discovery, "Closing all BLE connections");
551 0 : mSystemState->BleLayer()->CloseAllBleConnections();
552 : }
553 : #endif
554 : // Make sure that there will be no dangling pointer
555 0 : if (mDeviceInPASEEstablishment == device)
556 : {
557 0 : mDeviceInPASEEstablishment = nullptr;
558 : }
559 0 : if (mDeviceBeingCommissioned == device)
560 : {
561 0 : mDeviceBeingCommissioned = nullptr;
562 : }
563 :
564 : // Release the commissionee device after we have nulled out our pointers,
565 : // because that can call back in to us with error notifications as the
566 : // session is released.
567 0 : mCommissioneeDevicePool.ReleaseObject(device);
568 0 : }
569 :
570 0 : CHIP_ERROR DeviceCommissioner::GetDeviceBeingCommissioned(NodeId deviceId, CommissioneeDeviceProxy ** out_device)
571 : {
572 0 : VerifyOrReturnError(out_device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
573 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(deviceId);
574 :
575 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
576 :
577 0 : *out_device = device;
578 :
579 0 : return CHIP_NO_ERROR;
580 : }
581 :
582 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, const CommissioningParameters & params,
583 : DiscoveryType discoveryType, Optional<Dnssd::CommonResolutionData> resolutionData)
584 : {
585 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
586 :
587 0 : if (mDefaultCommissioner == nullptr)
588 : {
589 0 : ChipLogError(Controller, "No default commissioner is specified");
590 0 : return CHIP_ERROR_INCORRECT_STATE;
591 : }
592 0 : ReturnErrorOnFailure(mDefaultCommissioner->SetCommissioningParameters(params));
593 :
594 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
595 0 : resolutionData);
596 : }
597 :
598 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
599 : Optional<Dnssd::CommonResolutionData> resolutionData)
600 : {
601 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
602 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission, discoveryType,
603 0 : resolutionData);
604 : }
605 :
606 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params)
607 : {
608 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
609 0 : ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, params));
610 0 : return Commission(remoteDeviceId);
611 : }
612 :
613 0 : CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams,
614 : CommissioningParameters & commissioningParams)
615 : {
616 : MATTER_TRACE_SCOPE("PairDevice", "DeviceCommissioner");
617 0 : ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, rendezvousParams));
618 0 : return Commission(remoteDeviceId, commissioningParams);
619 : }
620 :
621 0 : CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType,
622 : Optional<Dnssd::CommonResolutionData> resolutionData)
623 : {
624 : MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
625 0 : return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kPaseOnly, discoveryType,
626 0 : resolutionData);
627 : }
628 :
629 0 : CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, RendezvousParameters & params)
630 : {
631 : MATTER_TRACE_SCOPE("EstablishPASEConnection", "DeviceCommissioner");
632 0 : CHIP_ERROR err = CHIP_NO_ERROR;
633 0 : CommissioneeDeviceProxy * device = nullptr;
634 0 : CommissioneeDeviceProxy * current = nullptr;
635 0 : Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any);
636 :
637 0 : Messaging::ExchangeContext * exchangeCtxt = nullptr;
638 0 : Optional<SessionHandle> session;
639 :
640 0 : VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
641 0 : VerifyOrExit(mDeviceInPASEEstablishment == nullptr, err = CHIP_ERROR_INCORRECT_STATE);
642 :
643 : // TODO(#13940): We need to specify the peer address for BLE transport in bindings.
644 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle ||
645 0 : params.GetPeerAddress().GetTransportType() == Transport::Type::kUndefined)
646 : {
647 : #if CONFIG_NETWORK_LAYER_BLE
648 : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
649 : ConnectBleTransportToSelf();
650 : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
651 0 : if (!params.HasBleLayer())
652 : {
653 0 : params.SetPeerAddress(Transport::PeerAddress::BLE());
654 : }
655 0 : peerAddress = Transport::PeerAddress::BLE();
656 : #endif // CONFIG_NETWORK_LAYER_BLE
657 : }
658 0 : else if (params.GetPeerAddress().GetTransportType() == Transport::Type::kTcp ||
659 0 : params.GetPeerAddress().GetTransportType() == Transport::Type::kUdp)
660 : {
661 0 : peerAddress = Transport::PeerAddress::UDP(params.GetPeerAddress().GetIPAddress(), params.GetPeerAddress().GetPort(),
662 0 : params.GetPeerAddress().GetInterface());
663 : }
664 :
665 0 : current = FindCommissioneeDevice(peerAddress);
666 0 : if (current != nullptr)
667 : {
668 0 : if (current->GetDeviceId() == remoteDeviceId)
669 : {
670 : // We might be able to just reuse its connection if it has one or is
671 : // working on one.
672 0 : if (current->IsSecureConnected())
673 : {
674 0 : if (mPairingDelegate)
675 : {
676 : // We already have an open secure session to this device, call the callback immediately and early return.
677 0 : mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR);
678 : }
679 0 : return CHIP_NO_ERROR;
680 : }
681 0 : if (current->IsSessionSetupInProgress())
682 : {
683 : // We're not connected yet, but we're in the process of connecting. Pairing delegate will get a callback when
684 : // connection completes
685 0 : return CHIP_NO_ERROR;
686 : }
687 : }
688 :
689 : // Either the consumer wants to assign a different device id to this
690 : // peer address now (so we can't reuse the commissionee device we have
691 : // already) or something has gone strange. Delete the old device, try
692 : // again.
693 0 : ChipLogError(Controller, "Found unconnected device, removing");
694 0 : ReleaseCommissioneeDevice(current);
695 : }
696 :
697 0 : device = mCommissioneeDevicePool.CreateObject();
698 0 : VerifyOrExit(device != nullptr, err = CHIP_ERROR_NO_MEMORY);
699 :
700 0 : mDeviceInPASEEstablishment = device;
701 0 : device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress);
702 0 : device->UpdateDeviceData(params.GetPeerAddress(), params.GetMRPConfig());
703 :
704 : #if CONFIG_NETWORK_LAYER_BLE
705 0 : if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle)
706 : {
707 0 : if (params.HasConnectionObject())
708 : {
709 0 : SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetConnectionObject()));
710 : }
711 0 : else if (params.HasDiscoveredObject())
712 : {
713 : // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
714 : // for later.
715 0 : mRendezvousParametersForDeviceDiscoveredOverBle = params;
716 0 : SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetDiscoveredObject(), this,
717 : OnDiscoveredDeviceOverBleSuccess,
718 : OnDiscoveredDeviceOverBleError));
719 0 : ExitNow(CHIP_NO_ERROR);
720 : }
721 0 : else if (params.HasDiscriminator())
722 : {
723 : // The RendezvousParameters argument needs to be recovered if the search succeed, so save them
724 : // for later.
725 0 : mRendezvousParametersForDeviceDiscoveredOverBle = params;
726 :
727 0 : SetupDiscriminator discriminator;
728 0 : discriminator.SetLongValue(params.GetDiscriminator());
729 0 : SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(
730 : discriminator, this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError));
731 0 : ExitNow(CHIP_NO_ERROR);
732 : }
733 : else
734 : {
735 0 : ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT);
736 : }
737 : }
738 : #endif
739 0 : session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), params.GetMRPConfig());
740 0 : VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY);
741 :
742 : // Allocate the exchange immediately before calling PASESession::Pair.
743 : //
744 : // PASESession::Pair takes ownership of the exchange and will free it on
745 : // error, but can only do this if it is actually called. Allocating the
746 : // exchange context right before calling Pair ensures that if allocation
747 : // succeeds, PASESession has taken ownership.
748 0 : exchangeCtxt = mSystemState->ExchangeMgr()->NewContext(session.Value(), &device->GetPairing());
749 0 : VerifyOrExit(exchangeCtxt != nullptr, err = CHIP_ERROR_INTERNAL);
750 :
751 0 : err = device->GetPairing().Pair(*mSystemState->SessionMgr(), params.GetSetupPINCode(), GetLocalMRPConfig(), exchangeCtxt, this);
752 0 : SuccessOrExit(err);
753 :
754 0 : exit:
755 0 : if (err != CHIP_NO_ERROR)
756 : {
757 0 : if (device != nullptr)
758 : {
759 0 : ReleaseCommissioneeDevice(device);
760 : }
761 : }
762 :
763 0 : return err;
764 0 : }
765 :
766 : #if CONFIG_NETWORK_LAYER_BLE
767 0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj)
768 : {
769 0 : auto self = static_cast<DeviceCommissioner *>(appState);
770 0 : auto device = self->mDeviceInPASEEstablishment;
771 :
772 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
773 : {
774 0 : auto remoteId = device->GetDeviceId();
775 :
776 0 : auto params = self->mRendezvousParametersForDeviceDiscoveredOverBle;
777 0 : params.SetConnectionObject(connObj);
778 0 : self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
779 :
780 0 : self->ReleaseCommissioneeDevice(device);
781 0 : LogErrorOnFailure(self->EstablishPASEConnection(remoteId, params));
782 0 : }
783 0 : }
784 :
785 0 : void DeviceCommissioner::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err)
786 : {
787 0 : auto self = static_cast<DeviceCommissioner *>(appState);
788 0 : auto device = self->mDeviceInPASEEstablishment;
789 :
790 0 : if (nullptr != device && device->GetDeviceTransportType() == Transport::Type::kBle)
791 : {
792 0 : self->ReleaseCommissioneeDevice(device);
793 0 : self->mRendezvousParametersForDeviceDiscoveredOverBle = RendezvousParameters();
794 :
795 : // Callback is required when BLE discovery fails, otherwise the caller will always be in a suspended state
796 : // A better way to handle it should define a new error code
797 0 : if (self->mPairingDelegate != nullptr)
798 : {
799 0 : self->mPairingDelegate->OnPairingComplete(err);
800 : }
801 : }
802 0 : }
803 : #endif // CONFIG_NETWORK_LAYER_BLE
804 :
805 0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningParameters & params)
806 : {
807 0 : if (mDefaultCommissioner == nullptr)
808 : {
809 0 : ChipLogError(Controller, "No default commissioner is specified");
810 0 : return CHIP_ERROR_INCORRECT_STATE;
811 : }
812 0 : ReturnErrorOnFailure(mDefaultCommissioner->SetCommissioningParameters(params));
813 0 : return Commission(remoteDeviceId);
814 : }
815 :
816 0 : CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId)
817 : {
818 : MATTER_TRACE_SCOPE("Commission", "DeviceCommissioner");
819 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
820 0 : if (device == nullptr || (!device->IsSecureConnected() && !device->IsSessionSetupInProgress()))
821 : {
822 0 : ChipLogError(Controller, "Invalid device for commissioning " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
823 0 : return CHIP_ERROR_INCORRECT_STATE;
824 : }
825 0 : if (!device->IsSecureConnected() && device != mDeviceInPASEEstablishment)
826 : {
827 : // We should not end up in this state because we won't attempt to establish more than one connection at a time.
828 0 : ChipLogError(Controller, "Device is not connected and not being paired " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
829 0 : return CHIP_ERROR_INCORRECT_STATE;
830 : }
831 :
832 0 : if (mCommissioningStage != CommissioningStage::kSecurePairing)
833 : {
834 0 : ChipLogError(Controller, "Commissioning already in progress - not restarting");
835 0 : return CHIP_ERROR_INCORRECT_STATE;
836 : }
837 :
838 0 : if (mDefaultCommissioner == nullptr)
839 : {
840 0 : ChipLogError(Controller, "No default commissioner is specified");
841 0 : return CHIP_ERROR_INCORRECT_STATE;
842 : }
843 :
844 0 : ChipLogProgress(Controller, "Commission called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
845 :
846 0 : mDefaultCommissioner->SetOperationalCredentialsDelegate(mOperationalCredentialsDelegate);
847 0 : if (device->IsSecureConnected())
848 : {
849 0 : mDefaultCommissioner->StartCommissioning(this, device);
850 : }
851 : else
852 : {
853 0 : mRunCommissioningAfterConnection = true;
854 : }
855 0 : return CHIP_NO_ERROR;
856 : }
857 :
858 : CHIP_ERROR
859 0 : DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * device,
860 : Credentials::AttestationVerificationResult attestationResult)
861 : {
862 : MATTER_TRACE_SCOPE("continueCommissioningDevice", "DeviceCommissioner");
863 0 : if (device == nullptr || device != mDeviceBeingCommissioned)
864 : {
865 0 : ChipLogError(Controller, "Invalid device for commissioning %p", device);
866 0 : return CHIP_ERROR_INCORRECT_STATE;
867 : }
868 0 : CommissioneeDeviceProxy * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
869 0 : if (commissioneeDevice == nullptr)
870 : {
871 0 : ChipLogError(Controller, "Couldn't find commissionee device");
872 0 : return CHIP_ERROR_INCORRECT_STATE;
873 : }
874 0 : if (!commissioneeDevice->IsSecureConnected() || commissioneeDevice != mDeviceBeingCommissioned)
875 : {
876 0 : ChipLogError(Controller, "Invalid device for commissioning after attestation failure: 0x" ChipLogFormatX64,
877 : ChipLogValueX64(commissioneeDevice->GetDeviceId()));
878 0 : return CHIP_ERROR_INCORRECT_STATE;
879 : }
880 :
881 0 : if (mCommissioningStage != CommissioningStage::kAttestationVerification)
882 : {
883 0 : ChipLogError(Controller, "Commissioning is not attestation verification phase");
884 0 : return CHIP_ERROR_INCORRECT_STATE;
885 : }
886 :
887 0 : if (mDefaultCommissioner == nullptr)
888 : {
889 0 : ChipLogError(Controller, "No default commissioner is specified");
890 0 : return CHIP_ERROR_INCORRECT_STATE;
891 : }
892 :
893 0 : ChipLogProgress(Controller, "Continuing commissioning after attestation failure for device ID 0x" ChipLogFormatX64,
894 : ChipLogValueX64(commissioneeDevice->GetDeviceId()));
895 :
896 0 : if (attestationResult != AttestationVerificationResult::kSuccess)
897 : {
898 0 : ChipLogError(Controller, "Client selected error: %u for failed 'Attestation Information' for device",
899 : to_underlying(attestationResult));
900 :
901 0 : CommissioningDelegate::CommissioningReport report;
902 0 : report.Set<AttestationErrorInfo>(attestationResult);
903 0 : CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
904 0 : }
905 : else
906 : {
907 0 : ChipLogProgress(Controller, "Overriding attestation failure per client and continuing commissioning");
908 0 : CommissioningStageComplete(CHIP_NO_ERROR);
909 : }
910 0 : return CHIP_NO_ERROR;
911 : }
912 :
913 0 : CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId)
914 : {
915 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
916 0 : VerifyOrReturnError(remoteDeviceId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
917 :
918 0 : ChipLogProgress(Controller, "StopPairing called for node ID 0x" ChipLogFormatX64, ChipLogValueX64(remoteDeviceId));
919 :
920 : // If we're still in the process of discovering the device, just stop the SetUpCodePairer
921 0 : if (mSetUpCodePairer.StopPairing(remoteDeviceId))
922 : {
923 0 : return CHIP_NO_ERROR;
924 : }
925 :
926 : // Otherwise we might be pairing and / or commissioning it.
927 0 : CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId);
928 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
929 :
930 0 : if (mDeviceBeingCommissioned == device)
931 : {
932 0 : CommissioningStageComplete(CHIP_ERROR_CANCELLED);
933 : }
934 : else
935 : {
936 0 : ReleaseCommissioneeDevice(device);
937 : }
938 0 : return CHIP_NO_ERROR;
939 : }
940 :
941 0 : CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId)
942 : {
943 : MATTER_TRACE_SCOPE("UnpairDevice", "DeviceCommissioner");
944 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
945 :
946 0 : return AutoCurrentFabricRemover::RemoveCurrentFabric(this, remoteDeviceId);
947 : }
948 :
949 0 : void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status)
950 : {
951 0 : if (mDeviceInPASEEstablishment != nullptr)
952 : {
953 : // Release the commissionee device. For BLE, this is stored,
954 : // for IP commissioning, we have taken a reference to the
955 : // operational node to send the completion command.
956 0 : ReleaseCommissioneeDevice(mDeviceInPASEEstablishment);
957 :
958 0 : if (mPairingDelegate != nullptr)
959 : {
960 0 : mPairingDelegate->OnPairingComplete(status);
961 : }
962 : }
963 0 : }
964 :
965 0 : void DeviceCommissioner::OnSessionEstablishmentError(CHIP_ERROR err)
966 : {
967 0 : if (mPairingDelegate != nullptr)
968 : {
969 0 : mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingFailed);
970 : }
971 :
972 0 : RendezvousCleanup(err);
973 0 : }
974 :
975 0 : void DeviceCommissioner::OnSessionEstablished(const SessionHandle & session)
976 : {
977 : // PASE session established.
978 0 : CommissioneeDeviceProxy * device = mDeviceInPASEEstablishment;
979 :
980 : // We are in the callback for this pairing. Reset so we can pair another device.
981 0 : mDeviceInPASEEstablishment = nullptr;
982 :
983 0 : VerifyOrReturn(device != nullptr, OnSessionEstablishmentError(CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR));
984 :
985 0 : CHIP_ERROR err = device->SetConnected(session);
986 0 : if (err != CHIP_NO_ERROR)
987 : {
988 0 : ChipLogError(Controller, "Failed in setting up secure channel: err %s", ErrorStr(err));
989 0 : OnSessionEstablishmentError(err);
990 0 : return;
991 : }
992 :
993 0 : ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake");
994 :
995 0 : if (mPairingDelegate != nullptr)
996 : {
997 0 : mPairingDelegate->OnPairingComplete(CHIP_NO_ERROR);
998 : }
999 :
1000 0 : if (mRunCommissioningAfterConnection)
1001 : {
1002 0 : mRunCommissioningAfterConnection = false;
1003 0 : mDefaultCommissioner->StartCommissioning(this, device);
1004 : }
1005 : }
1006 :
1007 0 : CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * device,
1008 : Credentials::CertificateType certificateType,
1009 : Optional<System::Clock::Timeout> timeout)
1010 : {
1011 : MATTER_TRACE_SCOPE("SendCertificateChainRequestCommand", "DeviceCommissioner");
1012 0 : ChipLogDetail(Controller, "Sending Certificate Chain request to %p device", device);
1013 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1014 :
1015 0 : OperationalCredentials::Commands::CertificateChainRequest::Type request;
1016 0 : request.certificateType = static_cast<OperationalCredentials::CertificateChainTypeEnum>(certificateType);
1017 0 : return SendCommand(device, request, OnCertificateChainResponse, OnCertificateChainFailureResponse, timeout);
1018 : }
1019 :
1020 0 : void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ERROR error)
1021 : {
1022 : MATTER_TRACE_SCOPE("OnCertificateChainFailureResponse", "DeviceCommissioner");
1023 0 : ChipLogProgress(Controller, "Device failed to receive the Certificate Chain request Response: %s", chip::ErrorStr(error));
1024 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1025 0 : commissioner->CommissioningStageComplete(error);
1026 0 : }
1027 :
1028 0 : void DeviceCommissioner::OnCertificateChainResponse(
1029 : void * context, const chip::app::Clusters::OperationalCredentials::Commands::CertificateChainResponse::DecodableType & response)
1030 : {
1031 : MATTER_TRACE_SCOPE("OnCertificateChainResponse", "DeviceCommissioner");
1032 0 : ChipLogProgress(Controller, "Received certificate chain from the device");
1033 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1034 :
1035 0 : CommissioningDelegate::CommissioningReport report;
1036 0 : report.Set<RequestedCertificate>(RequestedCertificate(response.certificate));
1037 :
1038 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1039 0 : }
1040 :
1041 0 : CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * device, const ByteSpan & attestationNonce,
1042 : Optional<System::Clock::Timeout> timeout)
1043 : {
1044 : MATTER_TRACE_SCOPE("SendAttestationRequestCommand", "DeviceCommissioner");
1045 0 : ChipLogDetail(Controller, "Sending Attestation request to %p device", device);
1046 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1047 :
1048 0 : OperationalCredentials::Commands::AttestationRequest::Type request;
1049 0 : request.attestationNonce = attestationNonce;
1050 :
1051 0 : ReturnErrorOnFailure(SendCommand(device, request, OnAttestationResponse, OnAttestationFailureResponse, timeout));
1052 0 : ChipLogDetail(Controller, "Sent Attestation request, waiting for the Attestation Information");
1053 0 : return CHIP_NO_ERROR;
1054 : }
1055 :
1056 0 : void DeviceCommissioner::OnAttestationFailureResponse(void * context, CHIP_ERROR error)
1057 : {
1058 : MATTER_TRACE_SCOPE("OnAttestationFailureResponse", "DeviceCommissioner");
1059 0 : ChipLogProgress(Controller, "Device failed to receive the Attestation Information Response: %s", chip::ErrorStr(error));
1060 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1061 0 : commissioner->CommissioningStageComplete(error);
1062 0 : }
1063 :
1064 0 : void DeviceCommissioner::OnAttestationResponse(void * context,
1065 : const OperationalCredentials::Commands::AttestationResponse::DecodableType & data)
1066 : {
1067 : MATTER_TRACE_SCOPE("OnAttestationResponse", "DeviceCommissioner");
1068 0 : ChipLogProgress(Controller, "Received Attestation Information from the device");
1069 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1070 :
1071 0 : CommissioningDelegate::CommissioningReport report;
1072 0 : report.Set<AttestationResponse>(AttestationResponse(data.attestationElements, data.attestationSignature));
1073 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1074 0 : }
1075 :
1076 0 : void DeviceCommissioner::OnDeviceAttestationInformationVerification(
1077 : void * context, const Credentials::DeviceAttestationVerifier::AttestationInfo & info, AttestationVerificationResult result)
1078 : {
1079 : MATTER_TRACE_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner");
1080 0 : DeviceCommissioner * commissioner = reinterpret_cast<DeviceCommissioner *>(context);
1081 :
1082 0 : if (!commissioner->mDeviceBeingCommissioned)
1083 : {
1084 0 : ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device");
1085 0 : return;
1086 : }
1087 :
1088 0 : auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
1089 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1090 :
1091 0 : if (result != AttestationVerificationResult::kSuccess)
1092 : {
1093 0 : CommissioningDelegate::CommissioningReport report;
1094 0 : report.Set<AttestationErrorInfo>(result);
1095 0 : if (result == AttestationVerificationResult::kNotImplemented)
1096 : {
1097 0 : ChipLogError(Controller,
1098 : "Failed in verifying 'Attestation Information' command received from the device due to default "
1099 : "DeviceAttestationVerifier Class not being overridden by a real implementation.");
1100 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_NOT_IMPLEMENTED, report);
1101 0 : return;
1102 : }
1103 :
1104 0 : ChipLogError(Controller,
1105 : "Failed in verifying 'Attestation Information' command received from the device: err %hu. Look at "
1106 : "AttestationVerificationResult enum to understand the errors",
1107 : static_cast<uint16_t>(result));
1108 : // Go look at AttestationVerificationResult enum in src/credentials/attestation_verifier/DeviceAttestationVerifier.h to
1109 : // understand the errors.
1110 :
1111 : // If a device attestation status delegate is installed, delegate handling of failure to the client and let them
1112 : // decide on whether to proceed further or not.
1113 0 : if (deviceAttestationDelegate)
1114 : {
1115 0 : commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
1116 : }
1117 : else
1118 : {
1119 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1120 : }
1121 0 : }
1122 : else
1123 : {
1124 0 : if (deviceAttestationDelegate && deviceAttestationDelegate->ShouldWaitAfterDeviceAttestation())
1125 : {
1126 0 : commissioner->ExtendArmFailSafeForDeviceAttestation(info, result);
1127 : }
1128 : else
1129 : {
1130 0 : ChipLogProgress(Controller, "Successfully validated 'Attestation Information' command received from the device.");
1131 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
1132 : }
1133 : }
1134 : }
1135 :
1136 0 : void DeviceCommissioner::OnArmFailSafeExtendedForDeviceAttestation(
1137 : void * context, const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
1138 : {
1139 : // If this function starts using "data", need to fix ExtendArmFailSafeForDeviceAttestation accordingly.
1140 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1141 :
1142 0 : if (!commissioner->mDeviceBeingCommissioned)
1143 : {
1144 0 : return;
1145 : }
1146 :
1147 0 : auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters();
1148 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1149 0 : if (deviceAttestationDelegate)
1150 : {
1151 0 : ChipLogProgress(Controller, "Device attestation completed, delegating continuation to client");
1152 0 : deviceAttestationDelegate->OnDeviceAttestationCompleted(commissioner, commissioner->mDeviceBeingCommissioned,
1153 0 : *commissioner->mAttestationDeviceInfo,
1154 : commissioner->mAttestationResult);
1155 : }
1156 : else
1157 : {
1158 0 : ChipLogProgress(Controller, "Device attestation failed and no delegate set, failing commissioning");
1159 0 : CommissioningDelegate::CommissioningReport report;
1160 0 : report.Set<AttestationErrorInfo>(commissioner->mAttestationResult);
1161 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1162 0 : }
1163 : }
1164 :
1165 0 : void DeviceCommissioner::OnFailedToExtendedArmFailSafeDeviceAttestation(void * context, CHIP_ERROR error)
1166 : {
1167 0 : ChipLogProgress(Controller, "Failed to extend fail-safe timer to handle attestation failure %s", chip::ErrorStr(error));
1168 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1169 :
1170 0 : CommissioningDelegate::CommissioningReport report;
1171 0 : report.Set<AttestationErrorInfo>(commissioner->mAttestationResult);
1172 0 : commissioner->CommissioningStageComplete(CHIP_ERROR_INTERNAL, report);
1173 0 : }
1174 :
1175 0 : void DeviceCommissioner::OnICDManagementRegisterClientResponse(
1176 : void * context, const app::Clusters::IcdManagement::Commands::RegisterClientResponse::DecodableType & data)
1177 : {
1178 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1179 0 : VerifyOrReturn(commissioner != nullptr, ChipLogProgress(Controller, "Command response callback with null context. Ignoring"));
1180 :
1181 0 : if (commissioner->mCommissioningStage != CommissioningStage::kICDRegistration)
1182 : {
1183 0 : return;
1184 : }
1185 :
1186 0 : if (commissioner->mDeviceBeingCommissioned == nullptr)
1187 : {
1188 0 : return;
1189 : }
1190 :
1191 0 : if (commissioner->mPairingDelegate != nullptr)
1192 : {
1193 0 : commissioner->mPairingDelegate->OnICDRegistrationComplete(commissioner->mDeviceBeingCommissioned->GetDeviceId(),
1194 0 : data.ICDCounter);
1195 : }
1196 0 : CommissioningDelegate::CommissioningReport report;
1197 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1198 0 : }
1199 :
1200 0 : bool DeviceCommissioner::ExtendArmFailSafe(DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout,
1201 : Optional<System::Clock::Timeout> commandTimeout, OnExtendFailsafeSuccess onSuccess,
1202 : OnExtendFailsafeFailure onFailure)
1203 : {
1204 : using namespace System;
1205 : using namespace System::Clock;
1206 0 : auto now = SystemClock().GetMonotonicTimestamp();
1207 0 : auto newFailSafeTimeout = now + Seconds16(armFailSafeTimeout);
1208 0 : if (newFailSafeTimeout < proxy->GetFailSafeExpirationTimestamp())
1209 : {
1210 0 : ChipLogProgress(
1211 : Controller, "Skipping arming failsafe: new time (%u seconds from now) before old time (%u seconds from now)",
1212 : armFailSafeTimeout, std::chrono::duration_cast<Seconds16>(proxy->GetFailSafeExpirationTimestamp() - now).count());
1213 0 : return false;
1214 : }
1215 :
1216 0 : uint64_t breadcrumb = static_cast<uint64_t>(step);
1217 0 : GeneralCommissioning::Commands::ArmFailSafe::Type request;
1218 0 : request.expiryLengthSeconds = armFailSafeTimeout;
1219 0 : request.breadcrumb = breadcrumb;
1220 0 : ChipLogProgress(Controller, "Arming failsafe (%u seconds)", request.expiryLengthSeconds);
1221 0 : CHIP_ERROR err = SendCommand(proxy, request, onSuccess, onFailure, kRootEndpointId, commandTimeout);
1222 0 : if (err != CHIP_NO_ERROR)
1223 : {
1224 0 : onFailure(this, err);
1225 : }
1226 : else
1227 : {
1228 : // TODO: Handle the situation when our command ends up erroring out
1229 : // asynchronously?
1230 0 : proxy->SetFailSafeExpirationTimestamp(newFailSafeTimeout);
1231 : }
1232 0 : return true;
1233 : }
1234 :
1235 0 : void DeviceCommissioner::ExtendArmFailSafeForDeviceAttestation(const Credentials::DeviceAttestationVerifier::AttestationInfo & info,
1236 : Credentials::AttestationVerificationResult result)
1237 : {
1238 0 : mAttestationResult = result;
1239 :
1240 0 : auto & params = mDefaultCommissioner->GetCommissioningParameters();
1241 0 : Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate();
1242 :
1243 0 : mAttestationDeviceInfo = Platform::MakeUnique<Credentials::DeviceAttestationVerifier::AttestationDeviceInfo>(info);
1244 :
1245 0 : auto expiryLengthSeconds = deviceAttestationDelegate->FailSafeExpiryTimeoutSecs();
1246 0 : bool waitForFailsafeExtension = expiryLengthSeconds.HasValue();
1247 0 : if (waitForFailsafeExtension)
1248 : {
1249 0 : ChipLogProgress(Controller, "Changing fail-safe timer to %u seconds to handle DA failure", expiryLengthSeconds.Value());
1250 : // Per spec, anything we do with the fail-safe armed must not time out
1251 : // in less than kMinimumCommissioningStepTimeout.
1252 : waitForFailsafeExtension =
1253 0 : ExtendArmFailSafe(mDeviceBeingCommissioned, mCommissioningStage, expiryLengthSeconds.Value(),
1254 0 : MakeOptional(kMinimumCommissioningStepTimeout), OnArmFailSafeExtendedForDeviceAttestation,
1255 : OnFailedToExtendedArmFailSafeDeviceAttestation);
1256 : }
1257 : else
1258 : {
1259 0 : ChipLogProgress(Controller, "Proceeding without changing fail-safe timer value as delegate has not set it");
1260 : }
1261 :
1262 0 : if (!waitForFailsafeExtension)
1263 : {
1264 : // Callee does not use data argument.
1265 0 : const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType data;
1266 0 : OnArmFailSafeExtendedForDeviceAttestation(this, data);
1267 : }
1268 0 : }
1269 :
1270 0 : CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info)
1271 : {
1272 : MATTER_TRACE_SCOPE("ValidateAttestationInfo", "DeviceCommissioner");
1273 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1274 0 : VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
1275 :
1276 0 : mDeviceAttestationVerifier->VerifyAttestationInformation(info, &mDeviceAttestationInformationVerificationCallback);
1277 :
1278 : // TODO: Validate Firmware Information
1279 :
1280 0 : return CHIP_NO_ERROR;
1281 : }
1282 :
1283 0 : CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
1284 : const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce)
1285 : {
1286 : MATTER_TRACE_SCOPE("ValidateCSR", "DeviceCommissioner");
1287 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1288 0 : VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE);
1289 :
1290 0 : P256PublicKey dacPubkey;
1291 0 : ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
1292 :
1293 : // Retrieve attestation challenge
1294 : ByteSpan attestationChallenge =
1295 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
1296 :
1297 : // The operational CA should also verify this on its end during NOC generation, if end-to-end attestation is desired.
1298 0 : return mDeviceAttestationVerifier->VerifyNodeOperationalCSRInformation(NOCSRElements, attestationChallenge,
1299 0 : AttestationSignature, dacPubkey, csrNonce);
1300 0 : }
1301 :
1302 0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(DeviceProxy * device, const ByteSpan & csrNonce,
1303 : Optional<System::Clock::Timeout> timeout)
1304 : {
1305 : MATTER_TRACE_SCOPE("SendOperationalCertificateSigningRequestCommand", "DeviceCommissioner");
1306 0 : ChipLogDetail(Controller, "Sending CSR request to %p device", device);
1307 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1308 :
1309 0 : OperationalCredentials::Commands::CSRRequest::Type request;
1310 0 : request.CSRNonce = csrNonce;
1311 :
1312 0 : ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateSigningRequest, OnCSRFailureResponse, timeout));
1313 0 : ChipLogDetail(Controller, "Sent CSR request, waiting for the CSR");
1314 0 : return CHIP_NO_ERROR;
1315 0 : }
1316 :
1317 0 : void DeviceCommissioner::OnCSRFailureResponse(void * context, CHIP_ERROR error)
1318 : {
1319 : MATTER_TRACE_SCOPE("OnCSRFailureResponse", "DeviceCommissioner");
1320 0 : ChipLogProgress(Controller, "Device failed to receive the CSR request Response: %s", chip::ErrorStr(error));
1321 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1322 0 : commissioner->CommissioningStageComplete(error);
1323 0 : }
1324 :
1325 0 : void DeviceCommissioner::OnOperationalCertificateSigningRequest(
1326 : void * context, const OperationalCredentials::Commands::CSRResponse::DecodableType & data)
1327 : {
1328 : MATTER_TRACE_SCOPE("OnOperationalCertificateSigningRequest", "DeviceCommissioner");
1329 0 : ChipLogProgress(Controller, "Received certificate signing request from the device");
1330 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1331 :
1332 0 : CommissioningDelegate::CommissioningReport report;
1333 0 : report.Set<CSRResponse>(CSRResponse(data.NOCSRElements, data.attestationSignature));
1334 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1335 0 : }
1336 :
1337 0 : void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac,
1338 : const ByteSpan & rcac, Optional<IdentityProtectionKeySpan> ipk,
1339 : Optional<NodeId> adminSubject)
1340 : {
1341 : MATTER_TRACE_SCOPE("OnDeviceNOCChainGeneration", "DeviceCommissioner");
1342 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1343 :
1344 : // The placeholder IPK is not satisfactory, but is there to fill the NocChain struct on error. It will still fail.
1345 0 : const uint8_t placeHolderIpk[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1346 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1347 0 : if (status == CHIP_NO_ERROR && !ipk.HasValue())
1348 : {
1349 0 : ChipLogError(Controller, "Did not have an IPK from the OperationalCredentialsIssuer! Cannot commission.");
1350 0 : status = CHIP_ERROR_INVALID_ARGUMENT;
1351 : }
1352 :
1353 0 : ChipLogProgress(Controller, "Received callback from the CA for NOC Chain generation. Status %s", ErrorStr(status));
1354 0 : if (status == CHIP_NO_ERROR && commissioner->mState != State::Initialized)
1355 : {
1356 0 : status = CHIP_ERROR_INCORRECT_STATE;
1357 : }
1358 0 : if (status != CHIP_NO_ERROR)
1359 : {
1360 0 : ChipLogError(Controller, "Failed in generating device's operational credentials. Error %s", ErrorStr(status));
1361 : }
1362 :
1363 : // TODO - Verify that the generated root cert matches with commissioner's root cert
1364 0 : CommissioningDelegate::CommissioningReport report;
1365 0 : report.Set<NocChain>(NocChain(noc, icac, rcac, ipk.HasValue() ? ipk.Value() : IdentityProtectionKeySpan(placeHolderIpk),
1366 0 : adminSubject.HasValue() ? adminSubject.Value() : commissioner->GetNodeId()));
1367 0 : commissioner->CommissioningStageComplete(status, report);
1368 0 : }
1369 :
1370 0 : CHIP_ERROR DeviceCommissioner::IssueNOCChain(const ByteSpan & NOCSRElements, NodeId nodeId,
1371 : chip::Callback::Callback<OnNOCChainGeneration> * callback)
1372 : {
1373 : MATTER_TRACE_SCOPE("IssueNOCChain", "DeviceCommissioner");
1374 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1375 :
1376 0 : ChipLogProgress(Controller, "Getting certificate chain for the device on fabric idx %u", static_cast<unsigned>(mFabricIndex));
1377 :
1378 0 : mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(nodeId);
1379 :
1380 0 : if (mFabricIndex != kUndefinedFabricIndex)
1381 : {
1382 0 : mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
1383 : }
1384 :
1385 : // Note: we don't have attestationSignature, attestationChallenge, DAC, PAI so we are just providing an empty ByteSpan
1386 : // for those arguments.
1387 0 : return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, ByteSpan(), ByteSpan(), ByteSpan(), ByteSpan(),
1388 0 : ByteSpan(), callback);
1389 : }
1390 :
1391 0 : CHIP_ERROR DeviceCommissioner::ProcessCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements,
1392 : const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & pai,
1393 : const ByteSpan & csrNonce)
1394 : {
1395 : MATTER_TRACE_SCOPE("ProcessOpCSR", "DeviceCommissioner");
1396 0 : VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE);
1397 :
1398 0 : ChipLogProgress(Controller, "Getting certificate chain for the device from the issuer");
1399 :
1400 0 : P256PublicKey dacPubkey;
1401 0 : ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(dac, dacPubkey));
1402 :
1403 : // Retrieve attestation challenge
1404 : ByteSpan attestationChallenge =
1405 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();
1406 :
1407 0 : mOperationalCredentialsDelegate->SetNodeIdForNextNOCRequest(proxy->GetDeviceId());
1408 :
1409 0 : if (mFabricIndex != kUndefinedFabricIndex)
1410 : {
1411 0 : mOperationalCredentialsDelegate->SetFabricIdForNextNOCRequest(GetFabricId());
1412 : }
1413 :
1414 0 : return mOperationalCredentialsDelegate->GenerateNOCChain(NOCSRElements, csrNonce, AttestationSignature, attestationChallenge,
1415 0 : dac, pai, &mDeviceNOCChainCallback);
1416 0 : }
1417 :
1418 0 : CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf,
1419 : const Optional<ByteSpan> & icaCertBuf,
1420 : const IdentityProtectionKeySpan ipk, const NodeId adminSubject,
1421 : Optional<System::Clock::Timeout> timeout)
1422 : {
1423 : MATTER_TRACE_SCOPE("SendOperationalCertificate", "DeviceCommissioner");
1424 :
1425 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1426 :
1427 0 : OperationalCredentials::Commands::AddNOC::Type request;
1428 0 : request.NOCValue = nocCertBuf;
1429 0 : request.ICACValue = icaCertBuf;
1430 0 : request.IPKValue = ipk;
1431 0 : request.caseAdminSubject = adminSubject;
1432 0 : request.adminVendorId = mVendorId;
1433 :
1434 0 : ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateAddResponse, OnAddNOCFailureResponse, timeout));
1435 :
1436 0 : ChipLogProgress(Controller, "Sent operational certificate to the device");
1437 :
1438 0 : return CHIP_NO_ERROR;
1439 0 : }
1440 :
1441 0 : CHIP_ERROR DeviceCommissioner::ConvertFromOperationalCertStatus(OperationalCredentials::NodeOperationalCertStatusEnum err)
1442 : {
1443 : using OperationalCredentials::NodeOperationalCertStatusEnum;
1444 0 : switch (err)
1445 : {
1446 0 : case NodeOperationalCertStatusEnum::kOk:
1447 0 : return CHIP_NO_ERROR;
1448 0 : case NodeOperationalCertStatusEnum::kInvalidPublicKey:
1449 0 : return CHIP_ERROR_INVALID_PUBLIC_KEY;
1450 0 : case NodeOperationalCertStatusEnum::kInvalidNodeOpId:
1451 0 : return CHIP_ERROR_WRONG_NODE_ID;
1452 0 : case NodeOperationalCertStatusEnum::kInvalidNOC:
1453 0 : return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
1454 0 : case NodeOperationalCertStatusEnum::kMissingCsr:
1455 0 : return CHIP_ERROR_INCORRECT_STATE;
1456 0 : case NodeOperationalCertStatusEnum::kTableFull:
1457 0 : return CHIP_ERROR_NO_MEMORY;
1458 0 : case NodeOperationalCertStatusEnum::kInvalidAdminSubject:
1459 0 : return CHIP_ERROR_INVALID_ADMIN_SUBJECT;
1460 0 : case NodeOperationalCertStatusEnum::kFabricConflict:
1461 0 : return CHIP_ERROR_FABRIC_EXISTS;
1462 0 : case NodeOperationalCertStatusEnum::kLabelConflict:
1463 0 : return CHIP_ERROR_INVALID_ARGUMENT;
1464 0 : case NodeOperationalCertStatusEnum::kInvalidFabricIndex:
1465 0 : return CHIP_ERROR_INVALID_FABRIC_INDEX;
1466 0 : case NodeOperationalCertStatusEnum::kUnknownEnumValue:
1467 : // Is this a reasonable value?
1468 0 : return CHIP_ERROR_CERT_LOAD_FAILED;
1469 : }
1470 :
1471 0 : return CHIP_ERROR_CERT_LOAD_FAILED;
1472 : }
1473 :
1474 0 : void DeviceCommissioner::OnAddNOCFailureResponse(void * context, CHIP_ERROR error)
1475 : {
1476 : MATTER_TRACE_SCOPE("OnAddNOCFailureResponse", "DeviceCommissioner");
1477 0 : ChipLogProgress(Controller, "Device failed to receive the operational certificate Response: %s", chip::ErrorStr(error));
1478 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1479 0 : commissioner->CommissioningStageComplete(error);
1480 0 : }
1481 :
1482 0 : void DeviceCommissioner::OnOperationalCertificateAddResponse(
1483 : void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data)
1484 : {
1485 : MATTER_TRACE_SCOPE("OnOperationalCertificateAddResponse", "DeviceCommissioner");
1486 0 : ChipLogProgress(Controller, "Device returned status %d on receiving the NOC", to_underlying(data.statusCode));
1487 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1488 :
1489 0 : CHIP_ERROR err = CHIP_NO_ERROR;
1490 :
1491 0 : VerifyOrExit(commissioner->mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
1492 :
1493 0 : VerifyOrExit(commissioner->mDeviceBeingCommissioned != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
1494 :
1495 0 : err = ConvertFromOperationalCertStatus(data.statusCode);
1496 0 : SuccessOrExit(err);
1497 :
1498 0 : err = commissioner->OnOperationalCredentialsProvisioningCompletion(commissioner->mDeviceBeingCommissioned);
1499 :
1500 0 : exit:
1501 0 : if (err != CHIP_NO_ERROR)
1502 : {
1503 0 : ChipLogProgress(Controller, "Add NOC failed with error %s", ErrorStr(err));
1504 0 : commissioner->CommissioningStageComplete(err);
1505 : }
1506 0 : }
1507 :
1508 0 : CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, const ByteSpan & rcac,
1509 : Optional<System::Clock::Timeout> timeout)
1510 : {
1511 : MATTER_TRACE_SCOPE("SendTrustedRootCertificate", "DeviceCommissioner");
1512 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1513 :
1514 0 : ChipLogProgress(Controller, "Sending root certificate to the device");
1515 :
1516 0 : OperationalCredentials::Commands::AddTrustedRootCertificate::Type request;
1517 0 : request.rootCACertificate = rcac;
1518 0 : ReturnErrorOnFailure(SendCommand(device, request, OnRootCertSuccessResponse, OnRootCertFailureResponse, timeout));
1519 :
1520 0 : ChipLogProgress(Controller, "Sent root certificate to the device");
1521 :
1522 0 : return CHIP_NO_ERROR;
1523 : }
1524 :
1525 0 : void DeviceCommissioner::OnRootCertSuccessResponse(void * context, const chip::app::DataModel::NullObjectType &)
1526 : {
1527 : MATTER_TRACE_SCOPE("OnRootCertSuccessResponse", "DeviceCommissioner");
1528 0 : ChipLogProgress(Controller, "Device confirmed that it has received the root certificate");
1529 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1530 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
1531 0 : }
1532 :
1533 0 : void DeviceCommissioner::OnRootCertFailureResponse(void * context, CHIP_ERROR error)
1534 : {
1535 : MATTER_TRACE_SCOPE("OnRootCertFailureResponse", "DeviceCommissioner");
1536 0 : ChipLogProgress(Controller, "Device failed to receive the root certificate Response: %s", chip::ErrorStr(error));
1537 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1538 0 : commissioner->CommissioningStageComplete(error);
1539 0 : }
1540 :
1541 0 : CHIP_ERROR DeviceCommissioner::OnOperationalCredentialsProvisioningCompletion(DeviceProxy * device)
1542 : {
1543 : MATTER_TRACE_SCOPE("OnOperationalCredentialsProvisioningCompletion", "DeviceCommissioner");
1544 0 : ChipLogProgress(Controller, "Operational credentials provisioned on device %p", device);
1545 0 : VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1546 :
1547 0 : if (mPairingDelegate != nullptr)
1548 : {
1549 0 : mPairingDelegate->OnStatusUpdate(DevicePairingDelegate::SecurePairingSuccess);
1550 : }
1551 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1552 :
1553 0 : return CHIP_NO_ERROR;
1554 : }
1555 :
1556 : #if CONFIG_NETWORK_LAYER_BLE
1557 : #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1558 : void DeviceCommissioner::ConnectBleTransportToSelf()
1559 : {
1560 : Transport::BLEBase & transport = std::get<Transport::BLE<1>>(mSystemState->TransportMgr()->GetTransport().GetTransports());
1561 : if (!transport.IsBleLayerTransportSetToSelf())
1562 : {
1563 : transport.SetBleLayerTransportToSelf();
1564 : }
1565 : }
1566 : #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1567 :
1568 0 : void DeviceCommissioner::CloseBleConnection()
1569 : {
1570 : // It is fine since we can only commission one device at the same time.
1571 : // We should be able to distinguish different BLE connections if we want
1572 : // to commission multiple devices at the same time over BLE.
1573 0 : mSystemState->BleLayer()->CloseAllBleConnections();
1574 0 : }
1575 : #endif
1576 :
1577 0 : CHIP_ERROR DeviceCommissioner::DiscoverCommissionableNodes(Dnssd::DiscoveryFilter filter)
1578 : {
1579 0 : ReturnErrorOnFailure(SetUpNodeDiscovery());
1580 0 : return mDNSResolver.DiscoverCommissionableNodes(filter);
1581 : }
1582 :
1583 0 : CHIP_ERROR DeviceCommissioner::StopCommissionableDiscovery()
1584 : {
1585 0 : return mDNSResolver.StopDiscovery();
1586 : }
1587 :
1588 0 : const Dnssd::DiscoveredNodeData * DeviceCommissioner::GetDiscoveredDevice(int idx)
1589 : {
1590 0 : return GetDiscoveredNode(idx);
1591 : }
1592 :
1593 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable
1594 :
1595 : CHIP_ERROR DeviceCommissioner::SetUdcListenPort(uint16_t listenPort)
1596 : {
1597 : if (mState == State::Initialized)
1598 : {
1599 : return CHIP_ERROR_INCORRECT_STATE;
1600 : }
1601 :
1602 : mUdcListenPort = listenPort;
1603 : return CHIP_NO_ERROR;
1604 : }
1605 :
1606 : void DeviceCommissioner::FindCommissionableNode(char * instanceName)
1607 : {
1608 : Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kInstanceName, instanceName);
1609 : DiscoverCommissionableNodes(filter);
1610 : }
1611 :
1612 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1613 :
1614 0 : void DeviceCommissioner::OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData)
1615 : {
1616 : #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1617 : if (mUdcServer != nullptr)
1618 : {
1619 : mUdcServer->OnCommissionableNodeFound(nodeData);
1620 : }
1621 : #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY
1622 0 : AbstractDnssdDiscoveryController::OnNodeDiscovered(nodeData);
1623 0 : mSetUpCodePairer.NotifyCommissionableDeviceDiscovered(nodeData);
1624 0 : }
1625 :
1626 0 : void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &)
1627 : {
1628 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1629 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
1630 0 : }
1631 :
1632 0 : void OnBasicFailure(void * context, CHIP_ERROR error)
1633 : {
1634 0 : ChipLogProgress(Controller, "Received failure response %s\n", chip::ErrorStr(error));
1635 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1636 0 : commissioner->CommissioningStageComplete(error);
1637 0 : }
1638 :
1639 0 : void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus)
1640 : {
1641 0 : commissioningCompletionStatus = completionStatus;
1642 :
1643 0 : if (completionStatus.err == CHIP_NO_ERROR)
1644 : {
1645 :
1646 0 : CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
1647 0 : if (commissionee != nullptr)
1648 : {
1649 0 : ReleaseCommissioneeDevice(commissionee);
1650 : }
1651 : // Send the callbacks, we're done.
1652 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1653 0 : SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
1654 : }
1655 0 : else if (completionStatus.failedStage.HasValue() && completionStatus.failedStage.Value() >= kWiFiNetworkSetup)
1656 : {
1657 : // If we were already doing network setup, we need to retain the pase session and start again from network setup stage.
1658 : // We do not need to reset the failsafe here because we want to keep everything on the device up to this point, so just
1659 : // send the completion callbacks.
1660 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1661 0 : SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
1662 : }
1663 : else
1664 : {
1665 : // If we've failed somewhere in the early stages (or we don't have a failedStage specified), we need to start from the
1666 : // beginning. However, because some of the commands can only be sent once per arm-failsafe, we also need to force a reset on
1667 : // the failsafe so we can start fresh on the next attempt.
1668 0 : GeneralCommissioning::Commands::ArmFailSafe::Type request;
1669 0 : request.expiryLengthSeconds = 0; // Expire immediately.
1670 0 : request.breadcrumb = 0;
1671 0 : ChipLogProgress(Controller, "Expiring failsafe on proxy %p", proxy);
1672 0 : mDeviceBeingCommissioned = proxy;
1673 : // We actually want to do the same thing on success or failure because we're already in a failure state
1674 0 : CHIP_ERROR err = SendCommand(proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure,
1675 : /* timeout = */ NullOptional);
1676 0 : if (err != CHIP_NO_ERROR)
1677 : {
1678 : // We won't get any async callbacks here, so just pretend like the
1679 : // command errored out async.
1680 0 : ChipLogError(Controller, "Failed to send command to disarm fail-safe: %" CHIP_ERROR_FORMAT, err.Format());
1681 0 : DisarmDone();
1682 0 : return;
1683 : }
1684 : }
1685 : }
1686 :
1687 0 : void DeviceCommissioner::OnDisarmFailsafe(void * context,
1688 : const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
1689 : {
1690 0 : ChipLogProgress(Controller, "Failsafe disarmed");
1691 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1692 0 : commissioner->DisarmDone();
1693 0 : }
1694 :
1695 0 : void DeviceCommissioner::OnDisarmFailsafeFailure(void * context, CHIP_ERROR error)
1696 : {
1697 0 : ChipLogProgress(Controller, "Received failure response when disarming failsafe%s\n", chip::ErrorStr(error));
1698 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1699 0 : commissioner->DisarmDone();
1700 0 : }
1701 :
1702 0 : void DeviceCommissioner::DisarmDone()
1703 : {
1704 : // If someone nulled out our mDeviceBeingCommissioned, there's nothing else
1705 : // to do here.
1706 0 : VerifyOrReturn(mDeviceBeingCommissioned != nullptr);
1707 :
1708 0 : NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId();
1709 : // At this point, we also want to close off the pase session so we need to re-establish
1710 0 : CommissioneeDeviceProxy * commissionee = FindCommissioneeDevice(nodeId);
1711 :
1712 : // Signal completion - this will reset mDeviceBeingCommissioned.
1713 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1714 0 : SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus);
1715 :
1716 : // If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection.
1717 0 : if (commissionee != nullptr)
1718 : {
1719 0 : ReleaseCommissioneeDevice(commissionee);
1720 : }
1721 : }
1722 :
1723 0 : void DeviceCommissioner::SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus)
1724 : {
1725 0 : mCommissioningStage = CommissioningStage::kSecurePairing;
1726 0 : if (mPairingDelegate == nullptr)
1727 : {
1728 0 : return;
1729 : }
1730 0 : mPairingDelegate->OnCommissioningComplete(nodeId, completionStatus.err);
1731 0 : PeerId peerId(GetCompressedFabricId(), nodeId);
1732 0 : if (completionStatus.err == CHIP_NO_ERROR)
1733 : {
1734 0 : mPairingDelegate->OnCommissioningSuccess(peerId);
1735 : }
1736 : else
1737 : {
1738 : // TODO: We should propogate detailed error information (commissioningError, networkCommissioningStatus) from
1739 : // completionStatus.
1740 0 : mPairingDelegate->OnCommissioningFailure(peerId, completionStatus.err, completionStatus.failedStage.ValueOr(kError),
1741 0 : completionStatus.attestationResult);
1742 : }
1743 : }
1744 :
1745 0 : void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report)
1746 : {
1747 : // Once this stage is complete, reset mDeviceBeingCommissioned - this will be reset when the delegate calls the next step.
1748 : MATTER_TRACE_SCOPE("CommissioningStageComplete", "DeviceCommissioner");
1749 0 : if (mDeviceBeingCommissioned == nullptr)
1750 : {
1751 : // We are getting a stray callback (e.g. due to un-cancellable
1752 : // operations) when we are not in fact commissioning anything. Just
1753 : // ignore it.
1754 0 : return;
1755 : }
1756 :
1757 0 : NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId();
1758 0 : DeviceProxy * proxy = mDeviceBeingCommissioned;
1759 0 : mDeviceBeingCommissioned = nullptr;
1760 :
1761 0 : if (mPairingDelegate != nullptr)
1762 : {
1763 0 : mPairingDelegate->OnCommissioningStatusUpdate(PeerId(GetCompressedFabricId(), nodeId), mCommissioningStage, err);
1764 : }
1765 :
1766 0 : if (mCommissioningDelegate == nullptr)
1767 : {
1768 0 : return;
1769 : }
1770 0 : report.stageCompleted = mCommissioningStage;
1771 0 : CHIP_ERROR status = mCommissioningDelegate->CommissioningStepFinished(err, report);
1772 0 : if (status != CHIP_NO_ERROR)
1773 : {
1774 : // Commissioning delegate will only return error if it failed to perform the appropriate commissioning step.
1775 : // In this case, we should complete the commissioning for it.
1776 0 : CompletionStatus completionStatus;
1777 0 : completionStatus.err = status;
1778 0 : completionStatus.failedStage = MakeOptional(report.stageCompleted);
1779 0 : mCommissioningStage = CommissioningStage::kCleanup;
1780 0 : mDeviceBeingCommissioned = proxy;
1781 0 : CleanupCommissioning(proxy, nodeId, completionStatus);
1782 0 : }
1783 : }
1784 :
1785 0 : void DeviceCommissioner::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
1786 : const SessionHandle & sessionHandle)
1787 : {
1788 : // CASE session established.
1789 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1790 0 : VerifyOrReturn(commissioner != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring"));
1791 :
1792 0 : if (commissioner->mCommissioningStage != CommissioningStage::kFindOperational)
1793 : {
1794 : // This call is definitely not us finding our commissionee device.
1795 : // This is presumably us trying to re-establish CASE on MRP failure.
1796 0 : return;
1797 : }
1798 :
1799 0 : if (commissioner->mDeviceBeingCommissioned == nullptr ||
1800 0 : commissioner->mDeviceBeingCommissioned->GetDeviceId() != sessionHandle->GetPeer().GetNodeId())
1801 : {
1802 : // Not the device we are trying to commission.
1803 0 : return;
1804 : }
1805 :
1806 0 : if (commissioner->mCommissioningDelegate != nullptr)
1807 : {
1808 0 : CommissioningDelegate::CommissioningReport report;
1809 0 : report.Set<OperationalNodeFoundData>(OperationalNodeFoundData(OperationalDeviceProxy(&exchangeMgr, sessionHandle)));
1810 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR, report);
1811 0 : }
1812 : }
1813 :
1814 0 : void DeviceCommissioner::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
1815 : {
1816 : // CASE session establishment failed.
1817 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
1818 :
1819 0 : ChipLogProgress(Controller, "Device connection failed. Error %s", ErrorStr(error));
1820 0 : VerifyOrReturn(commissioner != nullptr,
1821 : ChipLogProgress(Controller, "Device connection failure callback with null context. Ignoring"));
1822 :
1823 : // Ensure that commissioning stage advancement is done based on seeing an error.
1824 0 : if (error == CHIP_NO_ERROR)
1825 : {
1826 0 : ChipLogError(Controller, "Device connection failed without a valid error code. Making one up.");
1827 0 : error = CHIP_ERROR_INTERNAL;
1828 : }
1829 :
1830 0 : if (commissioner->mDeviceBeingCommissioned == nullptr ||
1831 0 : commissioner->mDeviceBeingCommissioned->GetDeviceId() != peerId.GetNodeId())
1832 : {
1833 : // Not the device we are trying to commission.
1834 0 : return;
1835 : }
1836 :
1837 0 : if (commissioner->mCommissioningStage == CommissioningStage::kFindOperational &&
1838 0 : commissioner->mCommissioningDelegate != nullptr)
1839 : {
1840 0 : commissioner->CommissioningStageComplete(error);
1841 : }
1842 : }
1843 :
1844 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
1845 : // No specific action to take on either success or failure here; we're just
1846 : // trying to bump the fail-safe, and if that fails it's not clear there's much
1847 : // we can to with that.
1848 0 : static void OnExtendFailsafeForCASERetryFailure(void * context, CHIP_ERROR error)
1849 : {
1850 0 : ChipLogError(Controller, "Failed to extend fail-safe for CASE retry: %" CHIP_ERROR_FORMAT, error.Format());
1851 0 : }
1852 : static void
1853 0 : OnExtendFailsafeForCASERetrySuccess(void * context,
1854 : const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
1855 : {
1856 0 : ChipLogProgress(Controller, "Status of extending fail-safe for CASE retry: %u", to_underlying(data.errorCode));
1857 0 : }
1858 :
1859 0 : void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error,
1860 : System::Clock::Seconds16 retryTimeout)
1861 : {
1862 0 : ChipLogError(Controller,
1863 : "Session establishment failed for " ChipLogFormatScopedNodeId ", error: %" CHIP_ERROR_FORMAT
1864 : ". Next retry expected to get a response to Sigma1 or fail within %d seconds",
1865 : ChipLogValueScopedNodeId(peerId), error.Format(), retryTimeout.count());
1866 :
1867 0 : auto self = static_cast<DeviceCommissioner *>(context);
1868 :
1869 : // We need to do the fail-safe arming over the PASE session.
1870 0 : auto * commissioneeDevice = self->FindCommissioneeDevice(peerId.GetNodeId());
1871 0 : if (!commissioneeDevice)
1872 : {
1873 : // Commissioning canceled, presumably. Just ignore the notification,
1874 : // not much we can do here.
1875 0 : return;
1876 : }
1877 :
1878 : // Extend by the default failsafe timeout plus our retry timeout, so we can
1879 : // be sure the fail-safe will not expire before we try the next time, if
1880 : // there will be a next time.
1881 : //
1882 : // TODO: Make it possible for our clients to control the exact timeout here?
1883 : uint16_t failsafeTimeout;
1884 0 : if (UINT16_MAX - retryTimeout.count() < kDefaultFailsafeTimeout)
1885 : {
1886 0 : failsafeTimeout = UINT16_MAX;
1887 : }
1888 : else
1889 : {
1890 0 : failsafeTimeout = static_cast<uint16_t>(retryTimeout.count() + kDefaultFailsafeTimeout);
1891 : }
1892 : // A false return from ExtendArmFailSafe is fine; we don't want to make the
1893 : // fail-safe shorter here.
1894 0 : self->ExtendArmFailSafe(commissioneeDevice, CommissioningStage::kFindOperational, failsafeTimeout,
1895 0 : MakeOptional(kMinimumCommissioningStepTimeout), OnExtendFailsafeForCASERetrySuccess,
1896 : OnExtendFailsafeForCASERetryFailure);
1897 : }
1898 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
1899 :
1900 : // ClusterStateCache::Callback impl
1901 0 : void DeviceCommissioner::OnDone(app::ReadClient *)
1902 : {
1903 0 : mReadClient = nullptr;
1904 0 : switch (mCommissioningStage)
1905 : {
1906 0 : case CommissioningStage::kReadCommissioningInfo:
1907 : // Silently complete the stage, data will be saved in attribute cache and
1908 : // will be parsed after all ReadCommissioningInfo stages are completed.
1909 0 : CommissioningStageComplete(CHIP_NO_ERROR);
1910 0 : break;
1911 0 : case CommissioningStage::kReadCommissioningInfo2:
1912 : // Note: Only parse commissioning info in the last ReadCommissioningInfo stage.
1913 0 : ParseCommissioningInfo();
1914 0 : break;
1915 0 : default:
1916 0 : break;
1917 : }
1918 0 : }
1919 :
1920 0 : void DeviceCommissioner::ParseCommissioningInfo()
1921 : {
1922 0 : CHIP_ERROR err = CHIP_NO_ERROR;
1923 0 : ReadCommissioningInfo info;
1924 :
1925 0 : err = ParseCommissioningInfo1(info);
1926 0 : if (err == CHIP_NO_ERROR)
1927 : {
1928 0 : err = ParseCommissioningInfo2(info);
1929 : }
1930 :
1931 : // Move ownership of mAttributeCache to the stack, but don't release it until this function returns.
1932 : // This way we don't have to make a copy while parsing commissioning info, and it won't
1933 : // affect future commissioning steps.
1934 : //
1935 : // The stack reference needs to survive until CommissioningStageComplete and OnReadCommissioningInfo
1936 : // return.
1937 0 : auto attributeCache = std::move(mAttributeCache);
1938 :
1939 0 : if (mPairingDelegate != nullptr)
1940 : {
1941 0 : mPairingDelegate->OnReadCommissioningInfo(info);
1942 : }
1943 :
1944 0 : CommissioningDelegate::CommissioningReport report;
1945 0 : report.Set<ReadCommissioningInfo>(info);
1946 0 : CommissioningStageComplete(err, report);
1947 0 : }
1948 :
1949 0 : CHIP_ERROR DeviceCommissioner::ParseCommissioningInfo1(ReadCommissioningInfo & info)
1950 : {
1951 : CHIP_ERROR err;
1952 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
1953 :
1954 : // Try to parse as much as we can here before returning, even if attributes
1955 : // are missing or cannot be decoded.
1956 : {
1957 : using namespace chip::app::Clusters::GeneralCommissioning;
1958 : using namespace chip::app::Clusters::GeneralCommissioning::Attributes;
1959 :
1960 0 : BasicCommissioningInfo::TypeInfo::DecodableType basicInfo;
1961 0 : err = mAttributeCache->Get<BasicCommissioningInfo::TypeInfo>(kRootEndpointId, basicInfo);
1962 0 : if (err == CHIP_NO_ERROR)
1963 : {
1964 0 : info.general.recommendedFailsafe = basicInfo.failSafeExpiryLengthSeconds;
1965 : }
1966 : else
1967 : {
1968 0 : ChipLogError(Controller, "Failed to read BasicCommissioningInfo: %" CHIP_ERROR_FORMAT, err.Format());
1969 0 : return_err = err;
1970 : }
1971 :
1972 0 : err = mAttributeCache->Get<RegulatoryConfig::TypeInfo>(kRootEndpointId, info.general.currentRegulatoryLocation);
1973 0 : if (err != CHIP_NO_ERROR)
1974 : {
1975 0 : ChipLogError(Controller, "Failed to read RegulatoryConfig: %" CHIP_ERROR_FORMAT, err.Format());
1976 0 : return_err = err;
1977 : }
1978 :
1979 0 : err = mAttributeCache->Get<LocationCapability::TypeInfo>(kRootEndpointId, info.general.locationCapability);
1980 0 : if (err != CHIP_NO_ERROR)
1981 : {
1982 0 : ChipLogError(Controller, "Failed to read LocationCapability: %" CHIP_ERROR_FORMAT, err.Format());
1983 0 : return_err = err;
1984 : }
1985 :
1986 0 : err = mAttributeCache->Get<Breadcrumb::TypeInfo>(kRootEndpointId, info.general.breadcrumb);
1987 0 : if (err != CHIP_NO_ERROR)
1988 : {
1989 0 : ChipLogError(Controller, "Failed to read Breadcrumb: %" CHIP_ERROR_FORMAT, err.Format());
1990 0 : return_err = err;
1991 : }
1992 : }
1993 :
1994 : {
1995 : using namespace chip::app::Clusters::BasicInformation;
1996 : using namespace chip::app::Clusters::BasicInformation::Attributes;
1997 :
1998 0 : err = mAttributeCache->Get<VendorID::TypeInfo>(kRootEndpointId, info.basic.vendorId);
1999 0 : return_err = err == CHIP_NO_ERROR ? return_err : err;
2000 :
2001 0 : err = mAttributeCache->Get<ProductID::TypeInfo>(kRootEndpointId, info.basic.productId);
2002 0 : return_err = err == CHIP_NO_ERROR ? return_err : err;
2003 : }
2004 : // Try to parse as much as we can here before returning, even if this is an error.
2005 0 : return_err = err == CHIP_NO_ERROR ? return_err : err;
2006 :
2007 : // Set the network cluster endpoints first so we can match up the connection
2008 : // times. Note that here we don't know what endpoints the network
2009 : // commissioning clusters might be on.
2010 0 : err = mAttributeCache->ForEachAttribute(
2011 0 : app::Clusters::NetworkCommissioning::Id, [this, &info](const app::ConcreteAttributePath & path) {
2012 : using namespace chip::app::Clusters;
2013 : using namespace chip::app::Clusters::NetworkCommissioning::Attributes;
2014 0 : if (path.mAttributeId != FeatureMap::Id)
2015 : {
2016 0 : return CHIP_NO_ERROR;
2017 : }
2018 : TLV::TLVReader reader;
2019 0 : if (this->mAttributeCache->Get(path, reader) == CHIP_NO_ERROR)
2020 : {
2021 0 : BitFlags<NetworkCommissioning::Feature> features;
2022 0 : if (app::DataModel::Decode(reader, features) == CHIP_NO_ERROR)
2023 : {
2024 0 : if (features.Has(NetworkCommissioning::Feature::kWiFiNetworkInterface))
2025 : {
2026 0 : ChipLogProgress(Controller, "----- NetworkCommissioning Features: has WiFi. endpointid = %u",
2027 : path.mEndpointId);
2028 0 : info.network.wifi.endpoint = path.mEndpointId;
2029 : }
2030 0 : else if (features.Has(NetworkCommissioning::Feature::kThreadNetworkInterface))
2031 : {
2032 0 : ChipLogProgress(Controller, "----- NetworkCommissioning Features: has Thread. endpointid = %u",
2033 : path.mEndpointId);
2034 0 : info.network.thread.endpoint = path.mEndpointId;
2035 : }
2036 0 : else if (features.Has(NetworkCommissioning::Feature::kEthernetNetworkInterface))
2037 : {
2038 0 : ChipLogProgress(Controller, "----- NetworkCommissioning Features: has Ethernet. endpointid = %u",
2039 : path.mEndpointId);
2040 0 : info.network.eth.endpoint = path.mEndpointId;
2041 : }
2042 : else
2043 : {
2044 0 : ChipLogProgress(Controller, "----- NetworkCommissioning Features: no features.");
2045 : // TODO: Gross workaround for the empty feature map on all clusters. Remove.
2046 0 : if (info.network.thread.endpoint == kInvalidEndpointId)
2047 : {
2048 0 : info.network.thread.endpoint = path.mEndpointId;
2049 : }
2050 0 : if (info.network.wifi.endpoint == kInvalidEndpointId)
2051 : {
2052 0 : info.network.wifi.endpoint = path.mEndpointId;
2053 : }
2054 : }
2055 : }
2056 : }
2057 0 : return CHIP_NO_ERROR;
2058 : });
2059 0 : return_err = err == CHIP_NO_ERROR ? return_err : err;
2060 :
2061 0 : err = mAttributeCache->ForEachAttribute(
2062 0 : app::Clusters::NetworkCommissioning::Id, [this, &info](const app::ConcreteAttributePath & path) {
2063 : using namespace chip::app::Clusters::NetworkCommissioning::Attributes;
2064 0 : if (path.mAttributeId != ConnectMaxTimeSeconds::Id)
2065 : {
2066 0 : return CHIP_NO_ERROR;
2067 : }
2068 : ConnectMaxTimeSeconds::TypeInfo::DecodableArgType time;
2069 0 : ReturnErrorOnFailure(this->mAttributeCache->Get<ConnectMaxTimeSeconds::TypeInfo>(path, time));
2070 0 : if (path.mEndpointId == info.network.wifi.endpoint)
2071 : {
2072 0 : info.network.wifi.minConnectionTime = time;
2073 : }
2074 0 : else if (path.mEndpointId == info.network.thread.endpoint)
2075 : {
2076 0 : info.network.thread.minConnectionTime = time;
2077 : }
2078 0 : else if (path.mEndpointId == info.network.eth.endpoint)
2079 : {
2080 0 : info.network.eth.minConnectionTime = time;
2081 : }
2082 0 : return CHIP_NO_ERROR;
2083 : });
2084 0 : return_err = err == CHIP_NO_ERROR ? return_err : err;
2085 :
2086 0 : ParseTimeSyncInfo(info);
2087 :
2088 0 : if (return_err != CHIP_NO_ERROR)
2089 : {
2090 0 : ChipLogError(Controller, "Error parsing commissioning information");
2091 : }
2092 :
2093 0 : return return_err;
2094 : }
2095 :
2096 0 : void DeviceCommissioner::ParseTimeSyncInfo(ReadCommissioningInfo & info)
2097 : {
2098 : using namespace app::Clusters;
2099 :
2100 : CHIP_ERROR err;
2101 : // If we fail to get the feature map, there's no viable time cluster, don't set anything.
2102 : TimeSynchronization::Attributes::FeatureMap::TypeInfo::DecodableType featureMap;
2103 0 : err = mAttributeCache->Get<TimeSynchronization::Attributes::FeatureMap::TypeInfo>(kRootEndpointId, featureMap);
2104 0 : if (err != CHIP_NO_ERROR)
2105 : {
2106 0 : info.requiresUTC = false;
2107 0 : info.requiresTimeZone = false;
2108 0 : info.requiresDefaultNTP = false;
2109 0 : info.requiresTrustedTimeSource = false;
2110 0 : return;
2111 : }
2112 0 : info.requiresUTC = true;
2113 0 : info.requiresTimeZone = featureMap & chip::to_underlying(TimeSynchronization::Feature::kTimeZone);
2114 0 : info.requiresDefaultNTP = featureMap & chip::to_underlying(TimeSynchronization::Feature::kNTPClient);
2115 0 : info.requiresTrustedTimeSource = featureMap & chip::to_underlying(TimeSynchronization::Feature::kTimeSyncClient);
2116 :
2117 0 : if (info.requiresTimeZone)
2118 : {
2119 0 : err = mAttributeCache->Get<TimeSynchronization::Attributes::TimeZoneListMaxSize::TypeInfo>(kRootEndpointId,
2120 0 : info.maxTimeZoneSize);
2121 0 : if (err != CHIP_NO_ERROR)
2122 : {
2123 : // This information should be available, let's do our best with what we have, but we can't set
2124 : // the time zone without this information
2125 0 : info.requiresTimeZone = false;
2126 : }
2127 0 : err =
2128 0 : mAttributeCache->Get<TimeSynchronization::Attributes::DSTOffsetListMaxSize::TypeInfo>(kRootEndpointId, info.maxDSTSize);
2129 0 : if (err != CHIP_NO_ERROR)
2130 : {
2131 0 : info.requiresTimeZone = false;
2132 : }
2133 : }
2134 0 : if (info.requiresDefaultNTP)
2135 : {
2136 0 : TimeSynchronization::Attributes::DefaultNTP::TypeInfo::DecodableType defaultNTP;
2137 0 : err = mAttributeCache->Get<TimeSynchronization::Attributes::DefaultNTP::TypeInfo>(kRootEndpointId, defaultNTP);
2138 0 : if (err == CHIP_NO_ERROR && (!defaultNTP.IsNull()) && (defaultNTP.Value().size() != 0))
2139 : {
2140 0 : info.requiresDefaultNTP = false;
2141 : }
2142 0 : }
2143 0 : if (info.requiresTrustedTimeSource)
2144 : {
2145 0 : TimeSynchronization::Attributes::TrustedTimeSource::TypeInfo::DecodableType trustedTimeSource;
2146 0 : err =
2147 0 : mAttributeCache->Get<TimeSynchronization::Attributes::TrustedTimeSource::TypeInfo>(kRootEndpointId, trustedTimeSource);
2148 :
2149 0 : if (err == CHIP_NO_ERROR && !trustedTimeSource.IsNull())
2150 : {
2151 0 : info.requiresTrustedTimeSource = false;
2152 : }
2153 0 : }
2154 : }
2155 :
2156 0 : CHIP_ERROR DeviceCommissioner::ParseCommissioningInfo2(ReadCommissioningInfo & info)
2157 : {
2158 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2159 :
2160 : using namespace chip::app::Clusters::GeneralCommissioning::Attributes;
2161 :
2162 0 : if (mAttributeCache->Get<SupportsConcurrentConnection::TypeInfo>(kRootEndpointId, info.supportsConcurrentConnection) !=
2163 0 : CHIP_NO_ERROR)
2164 : {
2165 : // May not be present so don't return the error code, non fatal, default concurrent
2166 0 : ChipLogError(Controller, "Failed to read SupportsConcurrentConnection: %" CHIP_ERROR_FORMAT, err.Format());
2167 0 : info.supportsConcurrentConnection = true;
2168 : }
2169 :
2170 0 : err = ParseFabrics(info);
2171 :
2172 0 : if (err == CHIP_NO_ERROR)
2173 : {
2174 0 : err = ParseICDInfo(info);
2175 : }
2176 :
2177 0 : return err;
2178 : }
2179 :
2180 0 : CHIP_ERROR DeviceCommissioner::ParseFabrics(ReadCommissioningInfo & info)
2181 : {
2182 : CHIP_ERROR err;
2183 0 : CHIP_ERROR return_err = CHIP_NO_ERROR;
2184 :
2185 : // We might not have requested a Fabrics attribute at all, so not having a
2186 : // value for it is not an error.
2187 0 : err = mAttributeCache->ForEachAttribute(OperationalCredentials::Id, [this, &info](const app::ConcreteAttributePath & path) {
2188 : using namespace chip::app::Clusters::OperationalCredentials::Attributes;
2189 : // this code is checking if the device is already on the commissioner's fabric.
2190 : // if a matching fabric is found, then remember the nodeId so that the commissioner
2191 : // can, if it decides to, cancel commissioning (before it fails in AddNoc) and know
2192 : // the device's nodeId on its fabric.
2193 0 : switch (path.mAttributeId)
2194 : {
2195 0 : case Fabrics::Id: {
2196 0 : Fabrics::TypeInfo::DecodableType fabrics;
2197 0 : ReturnErrorOnFailure(this->mAttributeCache->Get<Fabrics::TypeInfo>(path, fabrics));
2198 : // this is a best effort attempt to find a matching fabric, so no error checking on iter
2199 0 : auto iter = fabrics.begin();
2200 0 : while (iter.Next())
2201 : {
2202 0 : auto & fabricDescriptor = iter.GetValue();
2203 0 : ChipLogProgress(Controller,
2204 : "DeviceCommissioner::OnDone - fabric.vendorId=0x%04X fabric.fabricId=0x" ChipLogFormatX64
2205 : " fabric.nodeId=0x" ChipLogFormatX64,
2206 : fabricDescriptor.vendorID, ChipLogValueX64(fabricDescriptor.fabricID),
2207 : ChipLogValueX64(fabricDescriptor.nodeID));
2208 0 : if (GetFabricId() == fabricDescriptor.fabricID)
2209 : {
2210 0 : ChipLogProgress(Controller, "DeviceCommissioner::OnDone - found a matching fabric id");
2211 0 : chip::ByteSpan rootKeySpan = fabricDescriptor.rootPublicKey;
2212 0 : if (rootKeySpan.size() != Crypto::kP256_PublicKey_Length)
2213 : {
2214 0 : ChipLogError(Controller, "DeviceCommissioner::OnDone - fabric root key size mismatch %u != %u",
2215 : static_cast<unsigned>(rootKeySpan.size()),
2216 : static_cast<unsigned>(Crypto::kP256_PublicKey_Length));
2217 0 : continue;
2218 : }
2219 0 : P256PublicKeySpan rootPubKeySpan(rootKeySpan.data());
2220 0 : Crypto::P256PublicKey deviceRootPublicKey(rootPubKeySpan);
2221 :
2222 0 : Crypto::P256PublicKey commissionerRootPublicKey;
2223 0 : if (CHIP_NO_ERROR != GetRootPublicKey(commissionerRootPublicKey))
2224 : {
2225 0 : ChipLogError(Controller, "DeviceCommissioner::OnDone - error reading commissioner root public key");
2226 : }
2227 0 : else if (commissionerRootPublicKey.Matches(deviceRootPublicKey))
2228 : {
2229 0 : ChipLogProgress(Controller, "DeviceCommissioner::OnDone - fabric root keys match");
2230 0 : info.remoteNodeId = fabricDescriptor.nodeID;
2231 : }
2232 0 : }
2233 : }
2234 :
2235 0 : return CHIP_NO_ERROR;
2236 0 : }
2237 0 : default:
2238 0 : return CHIP_NO_ERROR;
2239 : }
2240 : });
2241 :
2242 0 : if (mPairingDelegate != nullptr)
2243 : {
2244 0 : mPairingDelegate->OnFabricCheck(info.remoteNodeId);
2245 : }
2246 :
2247 0 : return return_err;
2248 : }
2249 :
2250 0 : CHIP_ERROR DeviceCommissioner::ParseICDInfo(ReadCommissioningInfo & info)
2251 : {
2252 : using chip::app::Clusters::IcdManagement::UserActiveModeTriggerBitmap;
2253 :
2254 : CHIP_ERROR err;
2255 : IcdManagement::Attributes::FeatureMap::TypeInfo::DecodableType featureMap;
2256 0 : bool hasUserActiveModeTrigger = false;
2257 :
2258 0 : err = mAttributeCache->Get<IcdManagement::Attributes::FeatureMap::TypeInfo>(kRootEndpointId, featureMap);
2259 0 : if (err == CHIP_NO_ERROR)
2260 : {
2261 0 : info.icd.isLIT = !!(featureMap & to_underlying(IcdManagement::Feature::kLongIdleTimeSupport));
2262 0 : info.icd.checkInProtocolSupport = !!(featureMap & to_underlying(IcdManagement::Feature::kCheckInProtocolSupport));
2263 0 : hasUserActiveModeTrigger = !!(featureMap & to_underlying(IcdManagement::Feature::kUserActiveModeTrigger));
2264 : }
2265 0 : else if (err == CHIP_ERROR_KEY_NOT_FOUND)
2266 : {
2267 : // This key is optional so not an error
2268 0 : info.icd.isLIT = false;
2269 0 : err = CHIP_NO_ERROR;
2270 : }
2271 0 : else if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
2272 : {
2273 0 : app::StatusIB statusIB;
2274 0 : err = mAttributeCache->GetStatus(
2275 0 : app::ConcreteAttributePath(kRootEndpointId, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id), statusIB);
2276 0 : if (err == CHIP_NO_ERROR)
2277 : {
2278 0 : if (statusIB.mStatus == Protocols::InteractionModel::Status::UnsupportedCluster)
2279 : {
2280 0 : info.icd.isLIT = false;
2281 : }
2282 : else
2283 : {
2284 0 : err = statusIB.ToChipError();
2285 : }
2286 : }
2287 0 : }
2288 :
2289 0 : ReturnErrorOnFailure(err);
2290 :
2291 0 : info.icd.userActiveModeTriggerHint.ClearAll();
2292 0 : info.icd.userActiveModeTriggerInstruction = CharSpan();
2293 0 : if (hasUserActiveModeTrigger)
2294 : {
2295 : // Intentionally ignore errors since they are not mandatory.
2296 0 : bool activeModeTriggerInstructionRequired = false;
2297 :
2298 0 : err = mAttributeCache->Get<IcdManagement::Attributes::UserActiveModeTriggerHint::TypeInfo>(
2299 0 : kRootEndpointId, info.icd.userActiveModeTriggerHint);
2300 0 : if (err != CHIP_NO_ERROR)
2301 : {
2302 0 : ChipLogError(Controller, "IcdManagement.UserActiveModeTriggerHint expected, but failed to read.");
2303 0 : return err;
2304 : }
2305 :
2306 0 : activeModeTriggerInstructionRequired = info.icd.userActiveModeTriggerHint.HasAny(
2307 0 : UserActiveModeTriggerBitmap::kCustomInstruction, UserActiveModeTriggerBitmap::kActuateSensorSeconds,
2308 0 : UserActiveModeTriggerBitmap::kActuateSensorTimes, UserActiveModeTriggerBitmap::kActuateSensorLightsBlink,
2309 0 : UserActiveModeTriggerBitmap::kResetButtonLightsBlink, UserActiveModeTriggerBitmap::kResetButtonSeconds,
2310 0 : UserActiveModeTriggerBitmap::kResetButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonSeconds,
2311 0 : UserActiveModeTriggerBitmap::kSetupButtonTimes, UserActiveModeTriggerBitmap::kSetupButtonTimes,
2312 0 : UserActiveModeTriggerBitmap::kAppDefinedButton);
2313 :
2314 0 : if (activeModeTriggerInstructionRequired)
2315 : {
2316 0 : err = mAttributeCache->Get<IcdManagement::Attributes::UserActiveModeTriggerInstruction::TypeInfo>(
2317 0 : kRootEndpointId, info.icd.userActiveModeTriggerInstruction);
2318 0 : if (err != CHIP_NO_ERROR)
2319 : {
2320 0 : ChipLogError(Controller,
2321 : "IcdManagement.UserActiveModeTriggerInstruction expected for given active mode trigger hint, but "
2322 : "failed to read.");
2323 0 : return err;
2324 : }
2325 : }
2326 : }
2327 :
2328 0 : return err;
2329 : }
2330 :
2331 0 : void DeviceCommissioner::OnArmFailSafe(void * context,
2332 : const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data)
2333 : {
2334 0 : CommissioningDelegate::CommissioningReport report;
2335 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2336 :
2337 0 : ChipLogProgress(Controller, "Received ArmFailSafe response errorCode=%u", to_underlying(data.errorCode));
2338 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
2339 : {
2340 0 : err = CHIP_ERROR_INTERNAL;
2341 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
2342 : }
2343 :
2344 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2345 0 : commissioner->CommissioningStageComplete(err, report);
2346 0 : }
2347 :
2348 0 : void DeviceCommissioner::OnSetRegulatoryConfigResponse(
2349 : void * context, const GeneralCommissioning::Commands::SetRegulatoryConfigResponse::DecodableType & data)
2350 : {
2351 0 : CommissioningDelegate::CommissioningReport report;
2352 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2353 :
2354 0 : ChipLogProgress(Controller, "Received SetRegulatoryConfig response errorCode=%u", to_underlying(data.errorCode));
2355 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
2356 : {
2357 0 : err = CHIP_ERROR_INTERNAL;
2358 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
2359 : }
2360 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2361 0 : commissioner->CommissioningStageComplete(err, report);
2362 0 : }
2363 :
2364 0 : void DeviceCommissioner::OnSetTimeZoneResponse(void * context,
2365 : const TimeSynchronization::Commands::SetTimeZoneResponse::DecodableType & data)
2366 : {
2367 0 : CommissioningDelegate::CommissioningReport report;
2368 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2369 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2370 : TimeZoneResponseInfo info;
2371 0 : info.requiresDSTOffsets = data.DSTOffsetRequired;
2372 0 : report.Set<TimeZoneResponseInfo>(info);
2373 0 : commissioner->CommissioningStageComplete(err, report);
2374 0 : }
2375 :
2376 0 : void DeviceCommissioner::OnSetUTCError(void * context, CHIP_ERROR error)
2377 : {
2378 : // For SetUTCTime, we don't actually care if the commissionee didn't want out time, that's its choice
2379 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2380 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
2381 0 : }
2382 :
2383 0 : void DeviceCommissioner::OnScanNetworksFailure(void * context, CHIP_ERROR error)
2384 : {
2385 0 : ChipLogProgress(Controller, "Received ScanNetworks failure response %" CHIP_ERROR_FORMAT, error.Format());
2386 :
2387 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2388 :
2389 : // advance to the kNeedsNetworkCreds waiting step
2390 : // clear error so that we don't abort the commissioning when ScanNetworks fails
2391 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
2392 :
2393 0 : if (commissioner->GetPairingDelegate() != nullptr)
2394 : {
2395 0 : commissioner->GetPairingDelegate()->OnScanNetworksFailure(error);
2396 : }
2397 0 : }
2398 :
2399 0 : void DeviceCommissioner::OnScanNetworksResponse(void * context,
2400 : const NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & data)
2401 : {
2402 0 : CommissioningDelegate::CommissioningReport report;
2403 :
2404 0 : ChipLogProgress(Controller, "Received ScanNetwork response, networkingStatus=%u debugText=%s",
2405 : to_underlying(data.networkingStatus),
2406 : (data.debugText.HasValue() ? std::string(data.debugText.Value().data(), data.debugText.Value().size()).c_str()
2407 : : "none provided"));
2408 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2409 :
2410 : // advance to the kNeedsNetworkCreds waiting step
2411 0 : commissioner->CommissioningStageComplete(CHIP_NO_ERROR);
2412 :
2413 0 : if (commissioner->GetPairingDelegate() != nullptr)
2414 : {
2415 0 : commissioner->GetPairingDelegate()->OnScanNetworksSuccess(data);
2416 : }
2417 0 : }
2418 :
2419 0 : CHIP_ERROR DeviceCommissioner::NetworkCredentialsReady()
2420 : {
2421 0 : ReturnErrorCodeIf(mCommissioningStage != CommissioningStage::kNeedsNetworkCreds, CHIP_ERROR_INCORRECT_STATE);
2422 :
2423 : // need to advance to next step
2424 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2425 :
2426 0 : return CHIP_NO_ERROR;
2427 : }
2428 :
2429 0 : CHIP_ERROR DeviceCommissioner::ICDRegistrationInfoReady()
2430 : {
2431 0 : ReturnErrorCodeIf(mCommissioningStage != CommissioningStage::kICDGetRegistrationInfo, CHIP_ERROR_INCORRECT_STATE);
2432 :
2433 : // need to advance to next step
2434 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2435 :
2436 0 : return CHIP_NO_ERROR;
2437 : }
2438 :
2439 0 : void DeviceCommissioner::OnNetworkConfigResponse(void * context,
2440 : const NetworkCommissioning::Commands::NetworkConfigResponse::DecodableType & data)
2441 : {
2442 0 : CommissioningDelegate::CommissioningReport report;
2443 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2444 :
2445 0 : ChipLogProgress(Controller, "Received NetworkConfig response, networkingStatus=%u", to_underlying(data.networkingStatus));
2446 0 : if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
2447 : {
2448 0 : err = CHIP_ERROR_INTERNAL;
2449 0 : report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
2450 : }
2451 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2452 0 : commissioner->CommissioningStageComplete(err, report);
2453 0 : }
2454 :
2455 0 : void DeviceCommissioner::OnConnectNetworkResponse(
2456 : void * context, const NetworkCommissioning::Commands::ConnectNetworkResponse::DecodableType & data)
2457 : {
2458 0 : CommissioningDelegate::CommissioningReport report;
2459 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2460 :
2461 0 : ChipLogProgress(Controller, "Received ConnectNetwork response, networkingStatus=%u", to_underlying(data.networkingStatus));
2462 0 : if (data.networkingStatus != NetworkCommissioning::NetworkCommissioningStatusEnum::kSuccess)
2463 : {
2464 0 : err = CHIP_ERROR_INTERNAL;
2465 0 : report.Set<NetworkCommissioningStatusInfo>(data.networkingStatus);
2466 : }
2467 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2468 0 : commissioner->CommissioningStageComplete(err, report);
2469 0 : }
2470 :
2471 0 : void DeviceCommissioner::OnCommissioningCompleteResponse(
2472 : void * context, const GeneralCommissioning::Commands::CommissioningCompleteResponse::DecodableType & data)
2473 : {
2474 0 : CommissioningDelegate::CommissioningReport report;
2475 0 : CHIP_ERROR err = CHIP_NO_ERROR;
2476 :
2477 0 : ChipLogProgress(Controller, "Received CommissioningComplete response, errorCode=%u", to_underlying(data.errorCode));
2478 0 : if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk)
2479 : {
2480 0 : err = CHIP_ERROR_INTERNAL;
2481 0 : report.Set<CommissioningErrorInfo>(data.errorCode);
2482 : }
2483 0 : DeviceCommissioner * commissioner = static_cast<DeviceCommissioner *>(context);
2484 0 : commissioner->CommissioningStageComplete(err, report);
2485 0 : }
2486 :
2487 0 : void DeviceCommissioner::SendCommissioningReadRequest(DeviceProxy * proxy, Optional<System::Clock::Timeout> timeout,
2488 : app::AttributePathParams * readPaths, size_t readPathsSize)
2489 : {
2490 0 : app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
2491 0 : app::ReadPrepareParams readParams(proxy->GetSecureSession().Value());
2492 0 : readParams.mIsFabricFiltered = false;
2493 0 : if (timeout.HasValue())
2494 : {
2495 0 : readParams.mTimeout = timeout.Value();
2496 : }
2497 0 : readParams.mpAttributePathParamsList = readPaths;
2498 0 : readParams.mAttributePathParamsListSize = readPathsSize;
2499 :
2500 : // Take ownership of the attribute cache, so it can be released when SendRequest fails.
2501 0 : auto attributeCache = std::move(mAttributeCache);
2502 : auto readClient = chip::Platform::MakeUnique<app::ReadClient>(
2503 0 : engine, proxy->GetExchangeManager(), attributeCache->GetBufferedCallback(), app::ReadClient::InteractionType::Read);
2504 0 : CHIP_ERROR err = readClient->SendRequest(readParams);
2505 0 : if (err != CHIP_NO_ERROR)
2506 : {
2507 0 : ChipLogError(Controller, "Failed to send read request: %" CHIP_ERROR_FORMAT, err.Format());
2508 0 : CommissioningStageComplete(err);
2509 0 : return;
2510 : }
2511 0 : mAttributeCache = std::move(attributeCache);
2512 0 : mReadClient = std::move(readClient);
2513 0 : }
2514 :
2515 0 : void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, CommissioningStage step, CommissioningParameters & params,
2516 : CommissioningDelegate * delegate, EndpointId endpoint,
2517 : Optional<System::Clock::Timeout> timeout)
2518 : {
2519 0 : if (params.GetCompletionStatus().err == CHIP_NO_ERROR)
2520 : {
2521 0 : ChipLogProgress(Controller, "Performing next commissioning step '%s'", StageToString(step));
2522 : }
2523 : else
2524 : {
2525 0 : ChipLogProgress(Controller, "Performing next commissioning step '%s' with completion status = '%s'", StageToString(step),
2526 : params.GetCompletionStatus().err.AsString());
2527 : }
2528 :
2529 : // For now, we ignore errors coming in from the device since not all commissioning clusters are implemented on the device
2530 : // side.
2531 0 : mCommissioningStage = step;
2532 0 : mCommissioningDelegate = delegate;
2533 0 : mDeviceBeingCommissioned = proxy;
2534 : // TODO: Extend timeouts to the DAC and Opcert requests.
2535 :
2536 : // TODO(cecille): We probably want something better than this for breadcrumbs.
2537 0 : uint64_t breadcrumb = static_cast<uint64_t>(step);
2538 :
2539 0 : switch (step)
2540 : {
2541 0 : case CommissioningStage::kArmFailsafe: {
2542 0 : VerifyOrDie(endpoint == kRootEndpointId);
2543 : // Make sure the fail-safe value we set here actually ends up being used
2544 : // no matter what.
2545 0 : proxy->SetFailSafeExpirationTimestamp(System::Clock::kZero);
2546 0 : VerifyOrDie(ExtendArmFailSafe(proxy, step, params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout), timeout,
2547 : OnArmFailSafe, OnBasicFailure));
2548 : }
2549 0 : break;
2550 0 : case CommissioningStage::kReadCommissioningInfo: {
2551 0 : ChipLogProgress(Controller, "Sending read request for commissioning information");
2552 : // Allocate a new ClusterStateCache when starting reading the first batch of attributes.
2553 : // The cache will be released in:
2554 : // - SendCommissioningReadRequest when failing to send a read request.
2555 : // - ParseCommissioningInfo when the last ReadCommissioningInfo stage is completed.
2556 : // Currently, we have two ReadCommissioningInfo* stages.
2557 0 : mAttributeCache = Platform::MakeUnique<app::ClusterStateCache>(*this);
2558 :
2559 : // NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
2560 : // See R1.1, 2.11.2 Interaction Model Limits
2561 0 : app::AttributePathParams readPaths[9];
2562 : // Read all the feature maps for all the networking clusters on any endpoint to determine what is supported
2563 0 : readPaths[0] = app::AttributePathParams(app::Clusters::NetworkCommissioning::Id,
2564 : app::Clusters::NetworkCommissioning::Attributes::FeatureMap::Id);
2565 : // Get required general commissioning attributes on this endpoint (recommended failsafe time, regulatory location
2566 : // info, breadcrumb)
2567 0 : readPaths[1] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
2568 : app::Clusters::GeneralCommissioning::Attributes::Breadcrumb::Id);
2569 0 : readPaths[2] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
2570 : app::Clusters::GeneralCommissioning::Attributes::BasicCommissioningInfo::Id);
2571 0 : readPaths[3] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
2572 : app::Clusters::GeneralCommissioning::Attributes::RegulatoryConfig::Id);
2573 0 : readPaths[4] = app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
2574 : app::Clusters::GeneralCommissioning::Attributes::LocationCapability::Id);
2575 : // Read attributes from the basic info cluster (vendor id / product id / software version)
2576 0 : readPaths[5] = app::AttributePathParams(endpoint, app::Clusters::BasicInformation::Id,
2577 : app::Clusters::BasicInformation::Attributes::VendorID::Id);
2578 0 : readPaths[6] = app::AttributePathParams(endpoint, app::Clusters::BasicInformation::Id,
2579 : app::Clusters::BasicInformation::Attributes::ProductID::Id);
2580 : // Read the requested minimum connection times from all network commissioning clusters
2581 0 : readPaths[7] = app::AttributePathParams(app::Clusters::NetworkCommissioning::Id,
2582 : app::Clusters::NetworkCommissioning::Attributes::ConnectMaxTimeSeconds::Id);
2583 : // Read everything from the time cluster so we can assess what information needs to be set.
2584 0 : readPaths[8] = app::AttributePathParams(endpoint, app::Clusters::TimeSynchronization::Id);
2585 :
2586 0 : SendCommissioningReadRequest(proxy, timeout, readPaths, 9);
2587 : }
2588 0 : break;
2589 0 : case CommissioningStage::kReadCommissioningInfo2: {
2590 0 : size_t numberOfAttributes = 0;
2591 : // This is done in a separate step since we've already used up all the available read paths in the previous read step
2592 : // NOTE: this array cannot have more than 9 entries, since the spec mandates that server only needs to support 9
2593 : // See R1.1, 2.11.2 Interaction Model Limits
2594 :
2595 : // Currently, we have at most 5 attributes to read in this stage.
2596 0 : app::AttributePathParams readPaths[5];
2597 :
2598 : // Mandatory attribute
2599 0 : readPaths[numberOfAttributes++] =
2600 0 : app::AttributePathParams(endpoint, app::Clusters::GeneralCommissioning::Id,
2601 : app::Clusters::GeneralCommissioning::Attributes::SupportsConcurrentConnection::Id);
2602 :
2603 : // Read the current fabrics
2604 0 : if (params.GetCheckForMatchingFabric())
2605 : {
2606 0 : readPaths[numberOfAttributes++] =
2607 0 : app::AttributePathParams(OperationalCredentials::Id, OperationalCredentials::Attributes::Fabrics::Id);
2608 : }
2609 :
2610 0 : if (params.GetICDRegistrationStrategy() != ICDRegistrationStrategy::kIgnore)
2611 : {
2612 0 : readPaths[numberOfAttributes++] =
2613 0 : app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id);
2614 : }
2615 : // Always read the active mode trigger hint attributes to notify users about it.
2616 0 : readPaths[numberOfAttributes++] =
2617 0 : app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::UserActiveModeTriggerHint::Id);
2618 0 : readPaths[numberOfAttributes++] =
2619 0 : app::AttributePathParams(endpoint, IcdManagement::Id, IcdManagement::Attributes::UserActiveModeTriggerInstruction::Id);
2620 :
2621 0 : SendCommissioningReadRequest(proxy, timeout, readPaths, numberOfAttributes);
2622 : }
2623 0 : break;
2624 0 : case CommissioningStage::kConfigureUTCTime: {
2625 0 : TimeSynchronization::Commands::SetUTCTime::Type request;
2626 0 : uint64_t kChipEpochUsSinceUnixEpoch = static_cast<uint64_t>(kChipEpochSecondsSinceUnixEpoch) * chip::kMicrosecondsPerSecond;
2627 : System::Clock::Microseconds64 utcTime;
2628 0 : if (System::SystemClock().GetClock_RealTime(utcTime) != CHIP_NO_ERROR || utcTime.count() <= kChipEpochUsSinceUnixEpoch)
2629 : {
2630 : // We have no time to give, but that's OK, just complete this stage
2631 0 : CommissioningStageComplete(CHIP_NO_ERROR);
2632 0 : return;
2633 : }
2634 :
2635 0 : request.UTCTime = utcTime.count() - kChipEpochUsSinceUnixEpoch;
2636 : // For now, we assume a seconds granularity
2637 0 : request.granularity = TimeSynchronization::GranularityEnum::kSecondsGranularity;
2638 0 : CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnSetUTCError, endpoint, timeout);
2639 0 : if (err != CHIP_NO_ERROR)
2640 : {
2641 : // We won't get any async callbacks here, so just complete our stage.
2642 0 : ChipLogError(Controller, "Failed to send SetUTCTime command: %" CHIP_ERROR_FORMAT, err.Format());
2643 0 : CommissioningStageComplete(err);
2644 0 : return;
2645 : }
2646 0 : break;
2647 0 : }
2648 0 : case CommissioningStage::kConfigureTimeZone: {
2649 0 : if (!params.GetTimeZone().HasValue())
2650 : {
2651 0 : ChipLogError(Controller, "ConfigureTimeZone stage called with no time zone data");
2652 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2653 0 : return;
2654 : }
2655 0 : TimeSynchronization::Commands::SetTimeZone::Type request;
2656 0 : request.timeZone = params.GetTimeZone().Value();
2657 0 : CHIP_ERROR err = SendCommand(proxy, request, OnSetTimeZoneResponse, OnBasicFailure, endpoint, timeout);
2658 0 : if (err != CHIP_NO_ERROR)
2659 : {
2660 : // We won't get any async callbacks here, so just complete our stage.
2661 0 : ChipLogError(Controller, "Failed to send SetTimeZone command: %" CHIP_ERROR_FORMAT, err.Format());
2662 0 : CommissioningStageComplete(err);
2663 0 : return;
2664 : }
2665 0 : break;
2666 : }
2667 0 : case CommissioningStage::kConfigureDSTOffset: {
2668 0 : if (!params.GetDSTOffsets().HasValue())
2669 : {
2670 0 : ChipLogError(Controller, "ConfigureDSTOffset stage called with no DST data");
2671 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2672 0 : return;
2673 : }
2674 0 : TimeSynchronization::Commands::SetDSTOffset::Type request;
2675 0 : request.DSTOffset = params.GetDSTOffsets().Value();
2676 0 : CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
2677 0 : if (err != CHIP_NO_ERROR)
2678 : {
2679 : // We won't get any async callbacks here, so just complete our stage.
2680 0 : ChipLogError(Controller, "Failed to send SetDSTOffset command: %" CHIP_ERROR_FORMAT, err.Format());
2681 0 : CommissioningStageComplete(err);
2682 0 : return;
2683 : }
2684 0 : break;
2685 : }
2686 0 : case CommissioningStage::kConfigureDefaultNTP: {
2687 0 : if (!params.GetDefaultNTP().HasValue())
2688 : {
2689 0 : ChipLogError(Controller, "ConfigureDefaultNTP stage called with no default NTP data");
2690 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2691 0 : return;
2692 : }
2693 0 : TimeSynchronization::Commands::SetDefaultNTP::Type request;
2694 0 : request.defaultNTP = params.GetDefaultNTP().Value();
2695 0 : CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
2696 0 : if (err != CHIP_NO_ERROR)
2697 : {
2698 : // We won't get any async callbacks here, so just complete our stage.
2699 0 : ChipLogError(Controller, "Failed to send SetDefaultNTP command: %" CHIP_ERROR_FORMAT, err.Format());
2700 0 : CommissioningStageComplete(err);
2701 0 : return;
2702 : }
2703 0 : break;
2704 0 : }
2705 0 : case CommissioningStage::kScanNetworks: {
2706 0 : NetworkCommissioning::Commands::ScanNetworks::Type request;
2707 0 : if (params.GetWiFiCredentials().HasValue())
2708 : {
2709 0 : request.ssid.Emplace(params.GetWiFiCredentials().Value().ssid);
2710 : }
2711 0 : request.breadcrumb.Emplace(breadcrumb);
2712 0 : CHIP_ERROR err = SendCommand(proxy, request, OnScanNetworksResponse, OnScanNetworksFailure, endpoint, timeout);
2713 0 : if (err != CHIP_NO_ERROR)
2714 : {
2715 : // We won't get any async callbacks here, so just complete our stage.
2716 0 : ChipLogError(Controller, "Failed to send ScanNetworks command: %" CHIP_ERROR_FORMAT, err.Format());
2717 0 : CommissioningStageComplete(err);
2718 0 : return;
2719 : }
2720 0 : break;
2721 0 : }
2722 0 : case CommissioningStage::kNeedsNetworkCreds: {
2723 : // nothing to do, the OnScanNetworksSuccess and OnScanNetworksFailure callbacks provide indication to the
2724 : // DevicePairingDelegate that network credentials are needed.
2725 0 : break;
2726 : }
2727 0 : case CommissioningStage::kConfigRegulatory: {
2728 : // TODO(cecille): Worthwhile to keep this around as part of the class?
2729 : // TODO(cecille): Where is the country config actually set?
2730 0 : ChipLogProgress(Controller, "Setting Regulatory Config");
2731 : auto capability =
2732 0 : params.GetLocationCapability().ValueOr(app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor);
2733 : app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum regulatoryConfig;
2734 : // Value is only switchable on the devices with indoor/outdoor capability
2735 0 : if (capability == app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kIndoorOutdoor)
2736 : {
2737 : // If the device supports indoor and outdoor configs, use the setting from the commissioner, otherwise fall back to
2738 : // the current device setting then to outdoor (most restrictive)
2739 0 : if (params.GetDeviceRegulatoryLocation().HasValue())
2740 : {
2741 0 : regulatoryConfig = params.GetDeviceRegulatoryLocation().Value();
2742 0 : ChipLogProgress(Controller, "Setting regulatory config to %u from commissioner override",
2743 : static_cast<uint8_t>(regulatoryConfig));
2744 : }
2745 0 : else if (params.GetDefaultRegulatoryLocation().HasValue())
2746 : {
2747 0 : regulatoryConfig = params.GetDefaultRegulatoryLocation().Value();
2748 0 : ChipLogProgress(Controller, "No regulatory config supplied by controller, leaving as device default (%u)",
2749 : static_cast<uint8_t>(regulatoryConfig));
2750 : }
2751 : else
2752 : {
2753 0 : regulatoryConfig = app::Clusters::GeneralCommissioning::RegulatoryLocationTypeEnum::kOutdoor;
2754 0 : ChipLogProgress(Controller, "No overrride or device regulatory config supplied, setting to outdoor");
2755 : }
2756 : }
2757 : else
2758 : {
2759 0 : ChipLogProgress(Controller, "Device does not support configurable regulatory location");
2760 0 : regulatoryConfig = capability;
2761 : }
2762 :
2763 0 : CharSpan countryCode;
2764 0 : const auto & providedCountryCode = params.GetCountryCode();
2765 0 : if (providedCountryCode.HasValue())
2766 : {
2767 0 : countryCode = providedCountryCode.Value();
2768 : }
2769 : else
2770 : {
2771 : // Default to "XX", for lack of anything better.
2772 0 : countryCode = "XX"_span;
2773 : }
2774 :
2775 0 : GeneralCommissioning::Commands::SetRegulatoryConfig::Type request;
2776 0 : request.newRegulatoryConfig = regulatoryConfig;
2777 0 : request.countryCode = countryCode;
2778 0 : request.breadcrumb = breadcrumb;
2779 0 : CHIP_ERROR err = SendCommand(proxy, request, OnSetRegulatoryConfigResponse, OnBasicFailure, endpoint, timeout);
2780 0 : if (err != CHIP_NO_ERROR)
2781 : {
2782 : // We won't get any async callbacks here, so just complete our stage.
2783 0 : ChipLogError(Controller, "Failed to send SetRegulatoryConfig command: %" CHIP_ERROR_FORMAT, err.Format());
2784 0 : CommissioningStageComplete(err);
2785 0 : return;
2786 : }
2787 0 : }
2788 0 : break;
2789 0 : case CommissioningStage::kSendPAICertificateRequest: {
2790 0 : ChipLogProgress(Controller, "Sending request for PAI certificate");
2791 0 : CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kPAI, timeout);
2792 0 : if (err != CHIP_NO_ERROR)
2793 : {
2794 : // We won't get any async callbacks here, so just complete our stage.
2795 0 : ChipLogError(Controller, "Failed to send CertificateChainRequest command to get PAI: %" CHIP_ERROR_FORMAT,
2796 : err.Format());
2797 0 : CommissioningStageComplete(err);
2798 0 : return;
2799 : }
2800 0 : break;
2801 : }
2802 0 : case CommissioningStage::kSendDACCertificateRequest: {
2803 0 : ChipLogProgress(Controller, "Sending request for DAC certificate");
2804 0 : CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kDAC, timeout);
2805 0 : if (err != CHIP_NO_ERROR)
2806 : {
2807 : // We won't get any async callbacks here, so just complete our stage.
2808 0 : ChipLogError(Controller, "Failed to send CertificateChainRequest command to get DAC: %" CHIP_ERROR_FORMAT,
2809 : err.Format());
2810 0 : CommissioningStageComplete(err);
2811 0 : return;
2812 : }
2813 0 : break;
2814 : }
2815 0 : case CommissioningStage::kSendAttestationRequest: {
2816 0 : ChipLogProgress(Controller, "Sending Attestation Request to the device.");
2817 0 : if (!params.GetAttestationNonce().HasValue())
2818 : {
2819 0 : ChipLogError(Controller, "No attestation nonce found");
2820 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2821 0 : return;
2822 : }
2823 0 : CHIP_ERROR err = SendAttestationRequestCommand(proxy, params.GetAttestationNonce().Value(), timeout);
2824 0 : if (err != CHIP_NO_ERROR)
2825 : {
2826 : // We won't get any async callbacks here, so just complete our stage.
2827 0 : ChipLogError(Controller, "Failed to send AttestationRequest command: %" CHIP_ERROR_FORMAT, err.Format());
2828 0 : CommissioningStageComplete(err);
2829 0 : return;
2830 : }
2831 0 : break;
2832 : }
2833 0 : case CommissioningStage::kAttestationVerification: {
2834 0 : ChipLogProgress(Controller, "Verifying attestation");
2835 0 : if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() ||
2836 0 : !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
2837 0 : !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue())
2838 : {
2839 0 : ChipLogError(Controller, "Missing attestation information");
2840 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2841 0 : return;
2842 : }
2843 :
2844 : DeviceAttestationVerifier::AttestationInfo info(
2845 0 : params.GetAttestationElements().Value(),
2846 0 : proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(),
2847 0 : params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(),
2848 0 : params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value());
2849 :
2850 0 : if (ValidateAttestationInfo(info) != CHIP_NO_ERROR)
2851 : {
2852 0 : ChipLogError(Controller, "Error validating attestation information");
2853 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2854 0 : return;
2855 : }
2856 : }
2857 0 : break;
2858 0 : case CommissioningStage::kSendOpCertSigningRequest: {
2859 0 : if (!params.GetCSRNonce().HasValue())
2860 : {
2861 0 : ChipLogError(Controller, "No CSR nonce found");
2862 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2863 0 : return;
2864 : }
2865 0 : CHIP_ERROR err = SendOperationalCertificateSigningRequestCommand(proxy, params.GetCSRNonce().Value(), timeout);
2866 0 : if (err != CHIP_NO_ERROR)
2867 : {
2868 : // We won't get any async callbacks here, so just complete our stage.
2869 0 : ChipLogError(Controller, "Failed to send CSR request: %" CHIP_ERROR_FORMAT, err.Format());
2870 0 : CommissioningStageComplete(err);
2871 0 : return;
2872 : }
2873 0 : break;
2874 : }
2875 0 : case CommissioningStage::kValidateCSR: {
2876 0 : if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetCSRNonce().HasValue())
2877 : {
2878 0 : ChipLogError(Controller, "Unable to validate CSR");
2879 0 : return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2880 : }
2881 : // This is non-blocking, so send the callback immediately.
2882 0 : CHIP_ERROR err = ValidateCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
2883 0 : params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
2884 0 : params.GetCSRNonce().Value());
2885 0 : if (err != CHIP_NO_ERROR)
2886 : {
2887 0 : ChipLogError(Controller, "Unable to validate CSR");
2888 : }
2889 0 : CommissioningStageComplete(err);
2890 0 : return;
2891 : }
2892 : break;
2893 0 : case CommissioningStage::kGenerateNOCChain: {
2894 0 : if (!params.GetNOCChainGenerationParameters().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() ||
2895 0 : !params.GetCSRNonce().HasValue())
2896 : {
2897 0 : ChipLogError(Controller, "Unable to generate NOC chain parameters");
2898 0 : return CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2899 : }
2900 0 : CHIP_ERROR err = ProcessCSR(proxy, params.GetNOCChainGenerationParameters().Value().nocsrElements,
2901 0 : params.GetNOCChainGenerationParameters().Value().signature, params.GetDAC().Value(),
2902 0 : params.GetPAI().Value(), params.GetCSRNonce().Value());
2903 0 : if (err != CHIP_NO_ERROR)
2904 : {
2905 0 : ChipLogError(Controller, "Unable to process Op CSR");
2906 : // Handle error, and notify session failure to the commissioner application.
2907 0 : ChipLogError(Controller, "Failed to process the certificate signing request");
2908 : // TODO: Map error status to correct error code
2909 0 : CommissioningStageComplete(err);
2910 0 : return;
2911 : }
2912 : }
2913 0 : break;
2914 0 : case CommissioningStage::kSendTrustedRootCert: {
2915 0 : if (!params.GetRootCert().HasValue() || !params.GetNoc().HasValue())
2916 : {
2917 0 : ChipLogError(Controller, "No trusted root cert or NOC specified");
2918 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2919 0 : return;
2920 : }
2921 0 : CHIP_ERROR err = SendTrustedRootCertificate(proxy, params.GetRootCert().Value(), timeout);
2922 0 : if (err != CHIP_NO_ERROR)
2923 : {
2924 0 : ChipLogError(Controller, "Error sending trusted root certificate: %" CHIP_ERROR_FORMAT, err.Format());
2925 0 : CommissioningStageComplete(err);
2926 0 : return;
2927 : }
2928 :
2929 0 : err = proxy->SetPeerId(params.GetRootCert().Value(), params.GetNoc().Value());
2930 0 : if (err != CHIP_NO_ERROR)
2931 : {
2932 0 : ChipLogError(Controller, "Error setting peer id: %s", err.AsString());
2933 0 : CommissioningStageComplete(err);
2934 0 : return;
2935 : }
2936 0 : if (!IsOperationalNodeId(proxy->GetDeviceId()))
2937 : {
2938 0 : ChipLogError(Controller, "Given node ID is not an operational node ID");
2939 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2940 0 : return;
2941 : }
2942 : }
2943 0 : break;
2944 0 : case CommissioningStage::kSendNOC: {
2945 0 : if (!params.GetNoc().HasValue() || !params.GetIpk().HasValue() || !params.GetAdminSubject().HasValue())
2946 : {
2947 0 : ChipLogError(Controller, "AddNOC contents not specified");
2948 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2949 0 : return;
2950 : }
2951 0 : CHIP_ERROR err = SendOperationalCertificate(proxy, params.GetNoc().Value(), params.GetIcac(), params.GetIpk().Value(),
2952 0 : params.GetAdminSubject().Value(), timeout);
2953 0 : if (err != CHIP_NO_ERROR)
2954 : {
2955 : // We won't get any async callbacks here, so just complete our stage.
2956 0 : ChipLogError(Controller, "Error sending operational certificate: %" CHIP_ERROR_FORMAT, err.Format());
2957 0 : CommissioningStageComplete(err);
2958 0 : return;
2959 : }
2960 0 : break;
2961 : }
2962 0 : case CommissioningStage::kConfigureTrustedTimeSource: {
2963 0 : if (!params.GetTrustedTimeSource().HasValue())
2964 : {
2965 0 : ChipLogError(Controller, "ConfigureTrustedTimeSource stage called with no trusted time source data");
2966 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2967 0 : return;
2968 : }
2969 0 : TimeSynchronization::Commands::SetTrustedTimeSource::Type request;
2970 0 : request.trustedTimeSource = params.GetTrustedTimeSource().Value();
2971 0 : CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout);
2972 0 : if (err != CHIP_NO_ERROR)
2973 : {
2974 : // We won't get any async callbacks here, so just complete our stage.
2975 0 : ChipLogError(Controller, "Failed to send SendTrustedTimeSource command: %" CHIP_ERROR_FORMAT, err.Format());
2976 0 : CommissioningStageComplete(err);
2977 0 : return;
2978 : }
2979 0 : break;
2980 0 : }
2981 0 : case CommissioningStage::kWiFiNetworkSetup: {
2982 0 : if (!params.GetWiFiCredentials().HasValue())
2983 : {
2984 0 : ChipLogError(Controller, "No wifi credentials specified");
2985 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
2986 0 : return;
2987 : }
2988 :
2989 0 : NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type request;
2990 0 : request.ssid = params.GetWiFiCredentials().Value().ssid;
2991 0 : request.credentials = params.GetWiFiCredentials().Value().credentials;
2992 0 : request.breadcrumb.Emplace(breadcrumb);
2993 0 : CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
2994 0 : if (err != CHIP_NO_ERROR)
2995 : {
2996 : // We won't get any async callbacks here, so just complete our stage.
2997 0 : ChipLogError(Controller, "Failed to send AddOrUpdateWiFiNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
2998 0 : CommissioningStageComplete(err);
2999 0 : return;
3000 : }
3001 0 : }
3002 0 : break;
3003 0 : case CommissioningStage::kThreadNetworkSetup: {
3004 0 : if (!params.GetThreadOperationalDataset().HasValue())
3005 : {
3006 0 : ChipLogError(Controller, "No thread credentials specified");
3007 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3008 0 : return;
3009 : }
3010 0 : NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type request;
3011 0 : request.operationalDataset = params.GetThreadOperationalDataset().Value();
3012 0 : request.breadcrumb.Emplace(breadcrumb);
3013 0 : CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout);
3014 0 : if (err != CHIP_NO_ERROR)
3015 : {
3016 : // We won't get any async callbacks here, so just complete our stage.
3017 0 : ChipLogError(Controller, "Failed to send AddOrUpdateThreadNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3018 0 : CommissioningStageComplete(err);
3019 0 : return;
3020 : }
3021 0 : }
3022 0 : break;
3023 0 : case CommissioningStage::kFailsafeBeforeWiFiEnable:
3024 : FALLTHROUGH;
3025 : case CommissioningStage::kFailsafeBeforeThreadEnable:
3026 : // Before we try to do network enablement, make sure that our fail-safe
3027 : // is set far enough out that we can later try to do operational
3028 : // discovery without it timing out.
3029 0 : ExtendFailsafeBeforeNetworkEnable(proxy, params, step);
3030 0 : break;
3031 0 : case CommissioningStage::kWiFiNetworkEnable: {
3032 0 : if (!params.GetWiFiCredentials().HasValue())
3033 : {
3034 0 : ChipLogError(Controller, "No wifi credentials specified");
3035 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3036 0 : return;
3037 : }
3038 0 : NetworkCommissioning::Commands::ConnectNetwork::Type request;
3039 0 : request.networkID = params.GetWiFiCredentials().Value().ssid;
3040 0 : request.breadcrumb.Emplace(breadcrumb);
3041 :
3042 0 : CHIP_ERROR err = CHIP_NO_ERROR;
3043 0 : ChipLogProgress(Controller, "SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%d",
3044 : params.GetSupportsConcurrentConnection().Value());
3045 0 : err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
3046 :
3047 0 : if (err != CHIP_NO_ERROR)
3048 : {
3049 : // We won't get any async callbacks here, so just complete our stage.
3050 0 : ChipLogError(Controller, "Failed to send WiFi ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3051 0 : CommissioningStageComplete(err);
3052 0 : return;
3053 : }
3054 0 : }
3055 0 : break;
3056 0 : case CommissioningStage::kThreadNetworkEnable: {
3057 0 : ByteSpan extendedPanId;
3058 : chip::Thread::OperationalDataset operationalDataset;
3059 0 : if (!params.GetThreadOperationalDataset().HasValue() ||
3060 0 : operationalDataset.Init(params.GetThreadOperationalDataset().Value()) != CHIP_NO_ERROR ||
3061 0 : operationalDataset.GetExtendedPanIdAsByteSpan(extendedPanId) != CHIP_NO_ERROR)
3062 : {
3063 0 : ChipLogError(Controller, "Unable to get extended pan ID for thread operational dataset\n");
3064 0 : CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT);
3065 0 : return;
3066 : }
3067 0 : NetworkCommissioning::Commands::ConnectNetwork::Type request;
3068 0 : request.networkID = extendedPanId;
3069 0 : request.breadcrumb.Emplace(breadcrumb);
3070 0 : CHIP_ERROR err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout);
3071 0 : if (err != CHIP_NO_ERROR)
3072 : {
3073 : // We won't get any async callbacks here, so just complete our stage.
3074 0 : ChipLogError(Controller, "Failed to send Thread ConnectNetwork command: %" CHIP_ERROR_FORMAT, err.Format());
3075 0 : CommissioningStageComplete(err);
3076 0 : return;
3077 : }
3078 0 : }
3079 0 : break;
3080 0 : case CommissioningStage::kICDGetRegistrationInfo: {
3081 0 : GetPairingDelegate()->OnICDRegistrationInfoRequired();
3082 0 : return;
3083 : }
3084 : break;
3085 0 : case CommissioningStage::kICDRegistration: {
3086 0 : IcdManagement::Commands::RegisterClient::Type request;
3087 :
3088 0 : if (!(params.GetICDCheckInNodeId().HasValue() && params.GetICDMonitoredSubject().HasValue() &&
3089 0 : params.GetICDSymmetricKey().HasValue()))
3090 : {
3091 0 : ChipLogError(Controller, "No ICD Registration information provided!");
3092 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE);
3093 0 : return;
3094 : }
3095 :
3096 0 : request.checkInNodeID = params.GetICDCheckInNodeId().Value();
3097 0 : request.monitoredSubject = params.GetICDMonitoredSubject().Value();
3098 0 : request.key = params.GetICDSymmetricKey().Value();
3099 :
3100 0 : CHIP_ERROR err = SendCommand(proxy, request, OnICDManagementRegisterClientResponse, OnBasicFailure, endpoint, timeout);
3101 0 : if (err != CHIP_NO_ERROR)
3102 : {
3103 : // We won't get any async callbacks here, so just complete our stage.
3104 0 : ChipLogError(Controller, "Failed to send IcdManagement.RegisterClient command: %" CHIP_ERROR_FORMAT, err.Format());
3105 0 : CommissioningStageComplete(err);
3106 0 : return;
3107 : }
3108 0 : }
3109 0 : break;
3110 0 : case CommissioningStage::kICDSendStayActive: {
3111 : // TODO(#24259): Send StayActiveRequest once server supports this.
3112 0 : CommissioningStageComplete(CHIP_NO_ERROR);
3113 : }
3114 0 : break;
3115 0 : case CommissioningStage::kFindOperational: {
3116 : // If there is an error, CommissioningStageComplete will be called from OnDeviceConnectionFailureFn.
3117 0 : auto scopedPeerId = GetPeerScopedId(proxy->GetDeviceId());
3118 :
3119 : // If we ever had a commissioned device with this node ID before, we may
3120 : // have stale sessions to it. Make sure we don't re-use any of those,
3121 : // because clearly they are not related to this new device we are
3122 : // commissioning. We only care about sessions we might reuse, so just
3123 : // clearing the ones associated with our fabric index is good enough and
3124 : // we don't need to worry about ExpireAllSessionsOnLogicalFabric.
3125 0 : mSystemState->SessionMgr()->ExpireAllSessions(scopedPeerId);
3126 :
3127 0 : mSystemState->CASESessionMgr()->FindOrEstablishSession(scopedPeerId, &mOnDeviceConnectedCallback,
3128 : &mOnDeviceConnectionFailureCallback
3129 : #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
3130 : ,
3131 : /* attemptCount = */ 3, &mOnDeviceConnectionRetryCallback
3132 : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
3133 : );
3134 : }
3135 0 : break;
3136 0 : case CommissioningStage::kSendComplete: {
3137 : GeneralCommissioning::Commands::CommissioningComplete::Type request;
3138 0 : CHIP_ERROR err = SendCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout);
3139 0 : if (err != CHIP_NO_ERROR)
3140 : {
3141 : // We won't get any async callbacks here, so just complete our stage.
3142 0 : ChipLogError(Controller, "Failed to send CommissioningComplete command: %" CHIP_ERROR_FORMAT, err.Format());
3143 0 : CommissioningStageComplete(err);
3144 0 : return;
3145 : }
3146 : }
3147 0 : break;
3148 0 : case CommissioningStage::kCleanup:
3149 0 : CleanupCommissioning(proxy, proxy->GetDeviceId(), params.GetCompletionStatus());
3150 0 : break;
3151 0 : case CommissioningStage::kError:
3152 0 : mCommissioningStage = CommissioningStage::kSecurePairing;
3153 0 : break;
3154 0 : case CommissioningStage::kSecurePairing:
3155 0 : break;
3156 : }
3157 : }
3158 :
3159 0 : void DeviceCommissioner::ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params,
3160 : CommissioningStage step)
3161 : {
3162 0 : auto * commissioneeDevice = FindCommissioneeDevice(device->GetDeviceId());
3163 0 : if (device != commissioneeDevice)
3164 : {
3165 : // Not a commissionee device; just return.
3166 0 : ChipLogError(Controller, "Trying to extend fail-safe for an unknown commissionee with device id " ChipLogFormatX64,
3167 : ChipLogValueX64(device->GetDeviceId()));
3168 0 : CommissioningStageComplete(CHIP_ERROR_INCORRECT_STATE, CommissioningDelegate::CommissioningReport());
3169 0 : return;
3170 : }
3171 :
3172 : // Try to make sure we have at least enough time for our expected
3173 : // commissioning bits plus the MRP retries for a Sigma1.
3174 0 : uint16_t failSafeTimeoutSecs = params.GetFailsafeTimerSeconds().ValueOr(kDefaultFailsafeTimeout);
3175 0 : auto sigma1Timeout = CASESession::ComputeSigma1ResponseTimeout(commissioneeDevice->GetPairing().GetRemoteMRPConfig());
3176 0 : uint16_t sigma1TimeoutSecs = std::chrono::duration_cast<System::Clock::Seconds16>(sigma1Timeout).count();
3177 0 : if (UINT16_MAX - failSafeTimeoutSecs < sigma1TimeoutSecs)
3178 : {
3179 0 : failSafeTimeoutSecs = UINT16_MAX;
3180 : }
3181 : else
3182 : {
3183 0 : failSafeTimeoutSecs = static_cast<uint16_t>(failSafeTimeoutSecs + sigma1TimeoutSecs);
3184 : }
3185 :
3186 : // A false return from ExtendArmFailSafe is fine; we don't want to make the
3187 : // fail-safe shorter here.
3188 0 : if (!ExtendArmFailSafe(commissioneeDevice, step, failSafeTimeoutSecs, MakeOptional(kMinimumCommissioningStepTimeout),
3189 : OnArmFailSafe, OnBasicFailure))
3190 : {
3191 : // Just move on to the next step.
3192 0 : CommissioningStageComplete(CHIP_NO_ERROR, CommissioningDelegate::CommissioningReport());
3193 : }
3194 : }
3195 :
3196 0 : CHIP_ERROR DeviceController::GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const
3197 : {
3198 0 : const auto * fabricInfo = GetFabricInfo();
3199 0 : VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
3200 0 : return fabricInfo->GetCompressedFabricIdBytes(outBytes);
3201 : }
3202 :
3203 0 : CHIP_ERROR DeviceController::GetRootPublicKey(Crypto::P256PublicKey & outRootPublicKey) const
3204 : {
3205 0 : const auto * fabricTable = GetFabricTable();
3206 0 : VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INCORRECT_STATE);
3207 0 : return fabricTable->FetchRootPubkey(mFabricIndex, outRootPublicKey);
3208 : }
3209 :
3210 : } // namespace Controller
3211 : } // namespace chip
|