Skip to content

Commit a6e081a

Browse files
committed
[Fabric-Admin] Refactor to use API methods instead of PushCommand to talk to SDK
1 parent 32200d1 commit a6e081a

11 files changed

+282
-73
lines changed

examples/fabric-admin/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ static_library("fabric-admin-utils") {
8888
"device_manager/DeviceSubscriptionManager.h",
8989
"device_manager/DeviceSynchronization.cpp",
9090
"device_manager/DeviceSynchronization.h",
91+
"device_manager/PairingManager.cpp",
92+
"device_manager/PairingManager.h",
9193
"device_manager/UniqueIdGetter.cpp",
9294
"device_manager/UniqueIdGetter.h",
9395
]

examples/fabric-admin/commands/common/CHIPCommand.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "IcdManager.h"
2222
#include <controller/CHIPDeviceControllerFactory.h>
2323
#include <credentials/attestation_verifier/FileAttestationTrustStore.h>
24+
#include <device_manager/PairingManager.h>
2425
#include <lib/core/CHIPConfig.h>
2526
#include <lib/core/CHIPVendorIdentifiers.hpp>
2627
#include <lib/support/CodeUtils.h>
@@ -181,6 +182,8 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
181182
mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey,
182183
allowTestCdSigningKey);
183184

185+
ReturnLogErrorOnFailure(PairingManager::Instance().Init(&CurrentCommissioner()));
186+
184187
return CHIP_NO_ERROR;
185188
}
186189

examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp

+1-9
Original file line numberDiff line numberDiff line change
@@ -344,15 +344,7 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId)
344344
return CHIP_NO_ERROR;
345345
}
346346

347-
OpenCommissioningWindowCommand * openCommand =
348-
static_cast<OpenCommissioningWindowCommand *>(CommandMgr().GetCommandByName("pairing", "open-commissioning-window"));
349-
350-
if (openCommand == nullptr)
351-
{
352-
return CHIP_ERROR_NOT_IMPLEMENTED;
353-
}
354-
355-
openCommand->RegisterDelegate(this);
347+
PairingManager::Instance().RegisterOpenCommissioningWindowDelegate(this);
356348

357349
DeviceMgr().OpenRemoteDeviceCommissioningWindow(remoteId);
358350

examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#pragma once
2020

2121
#include <commands/common/CHIPCommand.h>
22-
#include <commands/pairing/OpenCommissioningWindowCommand.h>
2322
#include <commands/pairing/PairingCommand.h>
23+
#include <device_manager/PairingManager.h>
2424

2525
// Constants
2626
constexpr uint32_t kCommissionPrepareTimeMs = 500;

examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,6 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
7070
void OpenCommissioningWindowCommand::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err,
7171
chip::SetupPayload payload)
7272
{
73-
OpenCommissioningWindowCommand * self = static_cast<OpenCommissioningWindowCommand *>(context);
74-
if (self->mDelegate)
75-
{
76-
self->mDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
77-
self->UnregisterDelegate();
78-
}
79-
80-
LogErrorOnFailure(err);
8173
OnOpenBasicCommissioningWindowResponse(context, remoteId, err);
8274
}
8375

examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h

-11
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@
2222
#include <controller/CommissioningWindowOpener.h>
2323
#include <lib/support/CHIPMem.h>
2424

25-
class CommissioningWindowDelegate
26-
{
27-
public:
28-
virtual void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) = 0;
29-
virtual ~CommissioningWindowDelegate() = default;
30-
};
31-
3225
class OpenCommissioningWindowCommand : public CHIPCommand
3326
{
3427
public:
@@ -57,9 +50,6 @@ class OpenCommissioningWindowCommand : public CHIPCommand
5750
"params if absent");
5851
}
5952

60-
void RegisterDelegate(CommissioningWindowDelegate * delegate) { mDelegate = delegate; }
61-
void UnregisterDelegate() { mDelegate = nullptr; }
62-
6353
/////////// CHIPCommand Interface /////////
6454
CHIP_ERROR RunCommand() override;
6555

@@ -71,7 +61,6 @@ class OpenCommissioningWindowCommand : public CHIPCommand
7161
NodeId mNodeId;
7262
chip::EndpointId mEndpointId;
7363
chip::Controller::CommissioningWindowOpener::CommissioningWindowOption mCommissioningWindowOption;
74-
CommissioningWindowDelegate * mDelegate = nullptr;
7564
uint16_t mCommissioningWindowTimeout;
7665
uint32_t mIteration;
7766
uint16_t mDiscriminator;

examples/fabric-admin/device_manager/DeviceManager.cpp

+29-31
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <commands/interactive/InteractiveCommands.h>
2222
#include <crypto/RandUtils.h>
23+
#include <device_manager/PairingManager.h>
2324
#include <lib/support/StringBuilder.h>
2425

2526
#include <cstdio>
@@ -30,13 +31,12 @@ using namespace chip::app::Clusters;
3031

3132
namespace {
3233

33-
constexpr uint16_t kWindowTimeout = 300;
34-
constexpr uint16_t kIteration = 1000;
35-
constexpr uint16_t kSubscribeMinInterval = 0;
36-
constexpr uint16_t kSubscribeMaxInterval = 60;
37-
constexpr uint16_t kAggragatorEndpointId = 1;
38-
constexpr uint16_t kMaxDiscriminatorLength = 4095;
39-
constexpr uint8_t kEnhancedCommissioningMethod = 1;
34+
constexpr uint16_t kWindowTimeout = 300;
35+
constexpr uint16_t kIteration = 1000;
36+
constexpr uint16_t kSubscribeMinInterval = 0;
37+
constexpr uint16_t kSubscribeMaxInterval = 60;
38+
constexpr uint16_t kAggragatorEndpointId = 1;
39+
constexpr uint16_t kMaxDiscriminatorLength = 4095;
4040

4141
} // namespace
4242

@@ -116,18 +116,17 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId)
116116
}
117117

118118
void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations,
119-
uint32_t discriminator, const char * saltHex, const char * verifierHex)
119+
uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier)
120120
{
121-
ChipLogProgress(NotSpecified, "Open the commissioning window of device with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId));
121+
ChipLogProgress(NotSpecified, "Opening commissioning window for Node ID: " ChipLogFormatX64, ChipLogValueX64(nodeId));
122122

123123
// Open the commissioning window of a device within its own fabric.
124-
StringBuilder<kMaxCommandSize> commandBuilder;
125-
126-
commandBuilder.Add("pairing open-commissioning-window ");
127-
commandBuilder.AddFormat("%lu %d %d %d %d %d --salt hex:%s --verifier hex:%s", nodeId, kRootEndpointId,
128-
kEnhancedCommissioningMethod, commissioningTimeout, iterations, discriminator, saltHex, verifierHex);
129-
130-
PushCommand(commandBuilder.c_str());
124+
CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(nodeId, kRootEndpointId, commissioningTimeout, iterations,
125+
discriminator, salt, verifier);
126+
if (err != CHIP_NO_ERROR)
127+
{
128+
ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err));
129+
}
131130
}
132131

133132
void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpointId)
@@ -141,11 +140,15 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin
141140
uint16_t discriminator =
142141
Crypto::GetRandU16() % (kMaxDiscriminatorLength + 1); // Include the upper limit kMaxDiscriminatorLength
143142

144-
commandBuilder.Add("pairing open-commissioning-window ");
145-
commandBuilder.AddFormat("%lu %d %d %d %d %d", mRemoteBridgeNodeId, remoteEndpointId, kEnhancedCommissioningMethod,
146-
kWindowTimeout, kIteration, discriminator);
143+
ByteSpan emptySalt;
144+
ByteSpan emptyVerifier;
147145

148-
PushCommand(commandBuilder.c_str());
146+
CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(mRemoteBridgeNodeId, remoteEndpointId, kWindowTimeout,
147+
kIteration, discriminator, emptySalt, emptyVerifier);
148+
if (err != CHIP_NO_ERROR)
149+
{
150+
ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err));
151+
}
149152
}
150153

151154
void DeviceManager::PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp,
@@ -421,6 +424,7 @@ void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data)
421424
{
422425
CommissionerControl::Commands::ReverseOpenCommissioningWindow::DecodableType value;
423426
CHIP_ERROR error = app::DataModel::Decode(data, value);
427+
424428
if (error != CHIP_NO_ERROR)
425429
{
426430
ChipLogError(NotSpecified, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format());
@@ -432,18 +436,12 @@ void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data)
432436
ChipLogProgress(NotSpecified, " commissioningTimeout: %u", value.commissioningTimeout);
433437
ChipLogProgress(NotSpecified, " discriminator: %u", value.discriminator);
434438
ChipLogProgress(NotSpecified, " iterations: %u", value.iterations);
439+
ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier size: %lu", value.PAKEPasscodeVerifier.size());
440+
ChipLogProgress(NotSpecified, " salt size: %lu", value.salt.size());
435441

436-
char verifierHex[Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1];
437-
Encoding::BytesToHex(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size(), verifierHex, sizeof(verifierHex),
438-
Encoding::HexFlags::kNullTerminate);
439-
ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier: %s", verifierHex);
440-
441-
char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1];
442-
Encoding::BytesToHex(value.salt.data(), value.salt.size(), saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate);
443-
ChipLogProgress(NotSpecified, " salt: %s", saltHex);
444-
445-
OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator, saltHex,
446-
verifierHex);
442+
OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator,
443+
ByteSpan(value.salt.data(), value.salt.size()),
444+
ByteSpan(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size()));
447445
}
448446

449447
void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader & data)

examples/fabric-admin/device_manager/DeviceManager.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ class DeviceManager : public PairingDelegate
100100
* for deriving the PAKE (Password Authenticated Key Exchange) verifier.
101101
* @param discriminator The device-specific discriminator, determined during commissioning, which helps
102102
* to uniquely identify the device among others.
103-
* @param saltHex The hexadecimal-encoded salt used in the cryptographic operations for commissioning.
104-
* @param verifierHex The hexadecimal-encoded PAKE verifier used to authenticate the commissioning process.
103+
* @param salt The salt used in the cryptographic operations for commissioning.
104+
* @param verifier The PAKE verifier used to authenticate the commissioning process.
105105
*
106106
*/
107107
void OpenDeviceCommissioningWindow(chip::NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations,
108-
uint32_t discriminator, const char * saltHex, const char * verifierHex);
108+
uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier);
109109

110110
/**
111111
* @brief Open the commissioning window of a device from another fabric via its fabric bridge.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "PairingManager.h"
20+
21+
#include <controller/CommissioningDelegate.h>
22+
#include <controller/CurrentFabricRemover.h>
23+
#include <lib/support/Span.h>
24+
25+
using namespace ::chip;
26+
27+
Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> PairingManager::mWindowOpener;
28+
29+
PairingManager::PairingManager() :
30+
mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
31+
mOnOpenCommissioningWindowVerifierCallback(OnOpenCommissioningWindowVerifierResponse, this)
32+
{}
33+
34+
CHIP_ERROR PairingManager::Init(chip::Controller::DeviceCommissioner * commissioner)
35+
{
36+
mCommissioner = commissioner;
37+
return CHIP_NO_ERROR;
38+
}
39+
40+
CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId endpointId, uint16_t commissioningTimeout,
41+
uint32_t iterations, uint16_t discriminator, const ByteSpan & salt,
42+
const ByteSpan & verifier)
43+
{
44+
VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
45+
46+
auto * params = new CommissioningWindowParams();
47+
params->nodeId = nodeId;
48+
params->endpointId = endpointId;
49+
params->commissioningWindowTimeout = commissioningTimeout;
50+
params->iteration = iterations;
51+
params->discriminator = discriminator;
52+
53+
if (!salt.empty())
54+
{
55+
memcpy(params->saltBuffer, salt.data(), salt.size());
56+
params->salt = ByteSpan(params->saltBuffer, salt.size());
57+
}
58+
59+
if (!verifier.empty())
60+
{
61+
memcpy(params->verifierBuffer, verifier.data(), verifier.size());
62+
params->verifier = ByteSpan(params->verifierBuffer, verifier.size());
63+
}
64+
65+
// Schedule work on the Matter thread
66+
chip::DeviceLayer::PlatformMgr().ScheduleWork(OnOpenCommissioningWindow, reinterpret_cast<intptr_t>(params));
67+
68+
return CHIP_NO_ERROR;
69+
}
70+
71+
void PairingManager::OnOpenCommissioningWindow(intptr_t context)
72+
{
73+
auto * params = reinterpret_cast<CommissioningWindowParams *>(context);
74+
PairingManager & self = PairingManager::Instance();
75+
76+
if (self.mCommissioner == nullptr)
77+
{
78+
ChipLogError(AppServer, "Commissioner is null, cannot open commissioning window");
79+
return;
80+
}
81+
82+
mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(self.mCommissioner);
83+
84+
if (!params->verifier.empty())
85+
{
86+
if (params->salt.empty())
87+
{
88+
ChipLogError(AppServer, "Salt is required when verifier is set");
89+
return;
90+
}
91+
92+
CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams()
93+
.SetNodeId(params->nodeId)
94+
.SetEndpointId(params->endpointId)
95+
.SetTimeout(params->commissioningWindowTimeout)
96+
.SetIteration(params->iteration)
97+
.SetDiscriminator(params->discriminator)
98+
.SetVerifier(params->verifier)
99+
.SetSalt(params->salt)
100+
.SetCallback(&self.mOnOpenCommissioningWindowVerifierCallback));
101+
if (err != CHIP_NO_ERROR)
102+
{
103+
ChipLogError(AppServer, "Failed to open commissioning window with verifier: %s", ErrorStr(err));
104+
}
105+
}
106+
else
107+
{
108+
SetupPayload ignored;
109+
CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
110+
.SetNodeId(params->nodeId)
111+
.SetEndpointId(params->endpointId)
112+
.SetTimeout(params->commissioningWindowTimeout)
113+
.SetIteration(params->iteration)
114+
.SetDiscriminator(params->discriminator)
115+
.SetSetupPIN(NullOptional)
116+
.SetSalt(NullOptional)
117+
.SetCallback(&self.mOnOpenCommissioningWindowCallback),
118+
ignored);
119+
if (err != CHIP_NO_ERROR)
120+
{
121+
ChipLogError(AppServer, "Failed to open commissioning window with passcode: %s", ErrorStr(err));
122+
}
123+
}
124+
125+
// Clean up params
126+
delete params;
127+
}
128+
129+
void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, chip::SetupPayload payload)
130+
{
131+
PairingManager * self = static_cast<PairingManager *>(context);
132+
if (self->mCommissioningWindowDelegate)
133+
{
134+
self->mCommissioningWindowDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
135+
self->UnregisterOpenCommissioningWindowDelegate();
136+
}
137+
138+
OnOpenCommissioningWindowVerifierResponse(context, remoteId, err);
139+
}
140+
141+
void PairingManager::OnOpenCommissioningWindowVerifierResponse(void * context, NodeId remoteId, CHIP_ERROR err)
142+
{
143+
LogErrorOnFailure(err);
144+
145+
PairingManager * self = reinterpret_cast<PairingManager *>(context);
146+
VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnOpenCommissioningWindowCommand: context is null"));
147+
}

0 commit comments

Comments
 (0)