Skip to content

Commit 7d65b8f

Browse files
committed
Implemented the JCM mDNS advertisement and Open Commissioning Window
1 parent 2ed64bc commit 7d65b8f

22 files changed

+203
-25
lines changed

examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
2828
if (mCommissioningWindowOption == Controller::CommissioningWindowOpener::CommissioningWindowOption::kOriginalSetupCode)
2929
{
3030
return mWindowOpener->OpenBasicCommissioningWindow(mNodeId, System::Clock::Seconds16(mCommissioningWindowTimeout),
31-
&mOnOpenBasicCommissioningWindowCallback);
31+
&mOnOpenBasicCommissioningWindowCallback, mJointFabric.ValueOr(false));
3232
}
3333

3434
if (mCommissioningWindowOption == Controller::CommissioningWindowOpener::CommissioningWindowOption::kTokenWithRandomPIN)
@@ -41,7 +41,7 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
4141
.SetDiscriminator(mDiscriminator)
4242
.SetReadVIDPIDAttributes(true)
4343
.SetCallback(&mOnOpenCommissioningWindowCallback),
44-
ignored);
44+
ignored, mJointFabric.ValueOr(false));
4545
}
4646

4747
ChipLogError(chipTool, "Unknown commissioning window option: %d", to_underlying(mCommissioningWindowOption));

examples/chip-tool/commands/pairing/OpenCommissioningWindowCommand.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class OpenCommissioningWindowCommand : public CHIPCommand
4040
&mIteration, "Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0.");
4141
AddArgument("discriminator", 0, 4095, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0.");
4242
AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out.");
43+
AddArgument("joint-fabric", 0, 1, &mJointFabric, "Open Joint Fabric Commissioning Window.");
4344
}
4445

4546
/////////// CHIPCommand Interface /////////
@@ -56,6 +57,7 @@ class OpenCommissioningWindowCommand : public CHIPCommand
5657
uint16_t mDiscriminator;
5758

5859
chip::Optional<uint16_t> mTimeout;
60+
chip::Optional<bool> mJointFabric;
5961

6062
chip::Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> mWindowOpener;
6163

examples/chip-tool/commands/pairing/PairingCommand.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
368368
filter.code = 0;
369369
filter.instanceName = mDiscoveryFilterInstanceName;
370370
break;
371+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
372+
// TODO
373+
break;
371374
}
372375

373376
CurrentCommissioner().RegisterDeviceDiscoveryDelegate(this);

examples/chip-tool/commands/pairing/PairingCommand.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class PairingCommand : public CHIPCommand,
180180
break;
181181
case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
182182
case chip::Dnssd::DiscoveryFilterType::kCommissioner:
183+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
183184
break;
184185
case chip::Dnssd::DiscoveryFilterType::kDeviceType:
185186
AddArgument("device-type", 0, UINT16_MAX, &mDiscoveryFilterCode);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ class PairingCommand : public CHIPCommand,
158158
break;
159159
case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
160160
case chip::Dnssd::DiscoveryFilterType::kCommissioner:
161+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
161162
break;
162163
case chip::Dnssd::DiscoveryFilterType::kDeviceType:
163164
AddArgument("device-type", 0, UINT16_MAX, &mDiscoveryFilterCode);

src/app/clusters/joint-fabric-administrator-server/joint-fabric-administrator-server.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,67 @@ bool emberAfJointFabricAdministratorClusterAddICACCallback(
126126
return true;
127127
}
128128

129-
// TODO
130129
bool emberAfJointFabricAdministratorClusterOpenJointCommissioningWindowCallback(
131130
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
132131
const chip::app::Clusters::JointFabricAdministrator::Commands::OpenJointCommissioningWindow::DecodableType & commandData)
133132
{
134133
MATTER_TRACE_SCOPE("OpenJointCommissioningWindow", "JointFabricAdministrator");
134+
auto commissioningTimeout = System::Clock::Seconds16(commandData.commissioningTimeout);
135+
auto & pakeVerifier = commandData.PAKEPasscodeVerifier;
136+
auto & discriminator = commandData.discriminator;
137+
auto & iterations = commandData.iterations;
138+
auto & salt = commandData.salt;
139+
140+
Optional<AdministratorCommissioning::StatusCode> status = Optional<AdministratorCommissioning::StatusCode>::Missing();
141+
Status globalStatus = Status::Success;
142+
Spake2pVerifier verifier;
135143

136144
ChipLogProgress(Zcl, "Received command to open joint commissioning window");
137145

146+
FabricIndex fabricIndex = commandObj->GetAccessingFabricIndex();
147+
const FabricInfo * fabricInfo = Server::GetInstance().GetFabricTable().FindFabricWithIndex(fabricIndex);
148+
auto & failSafeContext = Server::GetInstance().GetFailSafeContext();
149+
auto & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
150+
151+
VerifyOrExit(fabricInfo != nullptr, status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
152+
VerifyOrExit(failSafeContext.IsFailSafeFullyDisarmed(), status.Emplace(AdministratorCommissioning::StatusCode::kBusy));
153+
154+
VerifyOrExit(!commissionMgr.IsCommissioningWindowOpen(), status.Emplace(AdministratorCommissioning::StatusCode::kBusy));
155+
VerifyOrExit(iterations >= kSpake2p_Min_PBKDF_Iterations,
156+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
157+
VerifyOrExit(iterations <= kSpake2p_Max_PBKDF_Iterations,
158+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
159+
VerifyOrExit(salt.size() >= kSpake2p_Min_PBKDF_Salt_Length,
160+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
161+
VerifyOrExit(salt.size() <= kSpake2p_Max_PBKDF_Salt_Length,
162+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
163+
VerifyOrExit(commissioningTimeout <= commissionMgr.MaxCommissioningTimeout(), globalStatus = Status::InvalidCommand);
164+
VerifyOrExit(commissioningTimeout >= commissionMgr.MinCommissioningTimeout(), globalStatus = Status::InvalidCommand);
165+
VerifyOrExit(discriminator <= kMaxDiscriminatorValue, globalStatus = Status::InvalidCommand);
166+
167+
VerifyOrExit(verifier.Deserialize(pakeVerifier) == CHIP_NO_ERROR,
168+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
169+
VerifyOrExit(commissionMgr.OpenJointCommissioningWindow(commissioningTimeout, discriminator, verifier, iterations, salt,
170+
fabricIndex, fabricInfo->GetVendorId()) == CHIP_NO_ERROR,
171+
status.Emplace(AdministratorCommissioning::StatusCode::kPAKEParameterError));
172+
ChipLogProgress(Zcl, "Commissioning window is now open");
173+
174+
exit:
175+
if (status.HasValue())
176+
{
177+
ChipLogError(Zcl, "Failed to open joint commissioning window. Cluster status 0x%02x", to_underlying(status.Value()));
178+
commandObj->AddClusterSpecificFailure(commandPath, to_underlying(status.Value()));
179+
}
180+
else
181+
{
182+
if (globalStatus != Status::Success)
183+
{
184+
ChipLogError(Zcl, "Failed to open joint commissioning window. Global status " ChipLogFormatIMStatus,
185+
ChipLogValueIMStatus(globalStatus));
186+
}
187+
commandObj->AddStatus(commandPath, globalStatus);
188+
}
189+
138190
return true;
139191
}
140192

src/app/server/CommissioningModeProvider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class DLL_EXPORT CommissioningModeProvider
3131
{
3232
public:
3333
virtual Dnssd::CommissioningMode GetCommissioningMode() const = 0;
34+
virtual bool IsJointFabricEnabled() = 0;
3435

3536
virtual ~CommissioningModeProvider() {}
3637
};

src/app/server/CommissioningWindowManager.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ void CommissioningWindowManager::Shutdown()
119119
void CommissioningWindowManager::ResetState()
120120
{
121121
mUseECM = false;
122+
mJCM = false;
122123

123124
mECMDiscriminator = 0;
124125
mECMIterations = 0;
@@ -390,6 +391,14 @@ CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(Seconds32
390391
return err;
391392
}
392393

394+
CHIP_ERROR CommissioningWindowManager::OpenJointCommissioningWindow(Seconds32 commissioningTimeout, uint16_t discriminator,
395+
Spake2pVerifier & verifier, uint32_t iterations, ByteSpan salt,
396+
FabricIndex fabricIndex, VendorId vendorId)
397+
{
398+
SetJCM(true);
399+
return OpenEnhancedCommissioningWindow(commissioningTimeout, discriminator, verifier, iterations, salt, fabricIndex, vendorId);
400+
}
401+
393402
void CommissioningWindowManager::CloseCommissioningWindow()
394403
{
395404
if (IsCommissioningWindowOpen())

src/app/server/CommissioningWindowManager.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler,
8888
Crypto::Spake2pVerifier & verifier, uint32_t iterations, chip::ByteSpan salt,
8989
FabricIndex fabricIndex, VendorId vendorId);
9090

91+
CHIP_ERROR OpenJointCommissioningWindow(System::Clock::Seconds32 commissioningTimeout, uint16_t discriminator,
92+
Crypto::Spake2pVerifier & verifier, uint32_t iterations, chip::ByteSpan salt,
93+
FabricIndex fabricIndex, VendorId vendorId);
94+
9195
void CloseCommissioningWindow();
9296

9397
app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum CommissioningWindowStatusForCluster() const;
@@ -102,6 +106,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler,
102106

103107
// CommissioningModeProvider implementation.
104108
Dnssd::CommissioningMode GetCommissioningMode() const override;
109+
bool IsJointFabricEnabled() override { return mJCM; }
105110

106111
//// UnsolicitedMessageHandler Implementation ////
107112
CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader,
@@ -127,6 +132,8 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler,
127132

128133
void SetBLE(bool ble) { mIsBLE = ble; }
129134

135+
void SetJCM(bool jcm) { mJCM = jcm; }
136+
130137
CHIP_ERROR SetTemporaryDiscriminator(uint16_t discriminator);
131138

132139
CHIP_ERROR RestoreDiscriminator();
@@ -190,6 +197,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler,
190197
app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen;
191198

192199
bool mIsBLE = true;
200+
bool mJCM = false;
193201

194202
PASESession mPairingSession;
195203

src/app/server/Dnssd.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,17 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi
270270
advertiseParameters.SetProductId(std::make_optional<uint16_t>(value));
271271
}
272272

273+
uint8_t jointFabricMode;
274+
if (mCommissioningModeProvider && mCommissioningModeProvider->IsJointFabricEnabled() &&
275+
DeviceLayer::GetDeviceInstanceInfoProvider()->GetJointFabricMode(jointFabricMode) != CHIP_NO_ERROR)
276+
{
277+
ChipLogDetail(Discovery, "Joint Fabric Mode not enabled or not known");
278+
}
279+
else
280+
{
281+
advertiseParameters.SetJointFabricMode(std::make_optional<uint16_t>(jointFabricMode));
282+
}
283+
273284
if (DeviceLayer::ConfigurationMgr().IsCommissionableDeviceTypeEnabled() &&
274285
DeviceLayer::ConfigurationMgr().GetDeviceTypeId(val32) == CHIP_NO_ERROR)
275286
{
@@ -363,11 +374,12 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi
363374

364375
auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance();
365376

366-
ChipLogProgress(Discovery, "Advertise commission parameter vendorID=%u productID=%u discriminator=%04u/%02u cm=%u cp=%u",
377+
ChipLogProgress(Discovery, "Advertise commission parameter vendorID=%u productID=%u discriminator=%04u/%02u cm=%u cp=%u jf=%u",
367378
advertiseParameters.GetVendorId().value_or(0), advertiseParameters.GetProductId().value_or(0),
368379
advertiseParameters.GetLongDiscriminator(), advertiseParameters.GetShortDiscriminator(),
369380
to_underlying(advertiseParameters.GetCommissioningMode()),
370-
advertiseParameters.GetCommissionerPasscodeSupported().value_or(false) ? 1 : 0);
381+
advertiseParameters.GetCommissionerPasscodeSupported().value_or(false) ? 1 : 0,
382+
advertiseParameters.GetJointFabricMode().value_or(0));
371383
return mdnsAdvertiser.Advertise(advertiseParameters);
372384
}
373385

src/controller/CommissioningWindowOpener.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ namespace chip {
3636
namespace Controller {
3737

3838
CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId deviceId, Seconds16 timeout,
39-
Callback::Callback<OnOpenBasicCommissioningWindow> * callback)
39+
Callback::Callback<OnOpenBasicCommissioningWindow> * callback,
40+
bool jointCommissioning)
4041
{
4142
VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
4243
mSetupPayload = SetupPayload();
@@ -49,6 +50,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId device
4950
mCommissioningWindowVerifierCallback = nullptr;
5051
mNodeId = deviceId;
5152
mCommissioningWindowTimeout = timeout;
53+
mJointCommissioning = jointCommissioning;
5254

5355
mNextStep = Step::kOpenCommissioningWindow;
5456
return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
@@ -58,7 +60,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, S
5860
uint16_t discriminator, Optional<uint32_t> setupPIN,
5961
Optional<ByteSpan> salt,
6062
Callback::Callback<OnOpenCommissioningWindow> * callback,
61-
SetupPayload & payload, bool readVIDPIDAttributes)
63+
SetupPayload & payload, bool readVIDPIDAttributes,
64+
bool jointCommissioning)
6265
{
6366
return OpenCommissioningWindow(CommissioningWindowPasscodeParams()
6467
.SetNodeId(deviceId)
@@ -69,11 +72,11 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, S
6972
.SetSalt(salt)
7073
.SetReadVIDPIDAttributes(readVIDPIDAttributes)
7174
.SetCallback(callback),
72-
payload);
75+
payload, jointCommissioning);
7376
}
7477

7578
CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowPasscodeParams & params,
76-
SetupPayload & payload)
79+
SetupPayload & payload, bool jointCommissioning)
7780
{
7881
VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
7982
VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
@@ -86,6 +89,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const Commissionin
8689
params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length),
8790
CHIP_ERROR_INVALID_ARGUMENT);
8891

92+
mJointCommissioning = jointCommissioning;
93+
8994
mSetupPayload = SetupPayload();
9095

9196
if (params.HasSetupPIN())
@@ -140,7 +145,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const Commissionin
140145
return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
141146
}
142147

143-
CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowVerifierParams & params)
148+
CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowVerifierParams & params,
149+
bool jointCommissioning)
144150
{
145151
VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
146152
VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
@@ -163,7 +169,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const Commissionin
163169
mPBKDFIterations = params.GetIteration();
164170
mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN;
165171
mDiscriminator.SetLongValue(params.GetDiscriminator());
166-
mTargetEndpointId = params.GetEndpointId();
172+
mTargetEndpointId = params.GetEndpointId();
173+
mJointCommissioning = jointCommissioning;
167174

168175
mNextStep = Step::kOpenCommissioningWindow;
169176

@@ -175,23 +182,38 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowInternal(Messaging:
175182
{
176183
ChipLogProgress(Controller, "OpenCommissioningWindow for device ID 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));
177184

178-
ClusterBase cluster(exchangeMgr, sessionHandle, mTargetEndpointId);
185+
ClusterBase cluster(exchangeMgr, sessionHandle, mJointCommissioning ? 1 : mTargetEndpointId);
179186

180187
if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode)
181188
{
182189
Spake2pVerifierSerialized serializedVerifier;
183190
MutableByteSpan serializedVerifierSpan(serializedVerifier);
184191
ReturnErrorOnFailure(mVerifier.Serialize(serializedVerifierSpan));
185192

186-
AdministratorCommissioning::Commands::OpenCommissioningWindow::Type request;
187-
request.commissioningTimeout = mCommissioningWindowTimeout.count();
188-
request.PAKEPasscodeVerifier = serializedVerifierSpan;
189-
request.discriminator = mDiscriminator.GetLongValue();
190-
request.iterations = mPBKDFIterations;
191-
request.salt = mPBKDFSalt;
192-
193-
ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
194-
OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
193+
if (mJointCommissioning == false)
194+
{
195+
AdministratorCommissioning::Commands::OpenCommissioningWindow::Type request;
196+
request.commissioningTimeout = mCommissioningWindowTimeout.count();
197+
request.PAKEPasscodeVerifier = serializedVerifierSpan;
198+
request.discriminator = mDiscriminator.GetLongValue();
199+
request.iterations = mPBKDFIterations;
200+
request.salt = mPBKDFSalt;
201+
202+
ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
203+
OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
204+
}
205+
else
206+
{
207+
JointFabricAdministrator::Commands::OpenJointCommissioningWindow::Type request;
208+
request.commissioningTimeout = mCommissioningWindowTimeout.count();
209+
request.PAKEPasscodeVerifier = serializedVerifierSpan;
210+
request.discriminator = mDiscriminator.GetLongValue();
211+
request.iterations = mPBKDFIterations;
212+
request.salt = mPBKDFSalt;
213+
214+
ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
215+
OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
216+
}
195217
}
196218
else
197219
{

0 commit comments

Comments
 (0)