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