Skip to content

Commit e1df193

Browse files
committed
Use dynamic OCW parameters in fabric bridge/admin app and RPC
1 parent 58e32d7 commit e1df193

12 files changed

+112
-37
lines changed

examples/common/pigweed/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pw_proto_library("button_service") {
8282

8383
pw_proto_library("fabric_admin_service") {
8484
sources = [ "protos/fabric_admin_service.proto" ]
85+
inputs = [ "protos/fabric_admin_service.options" ]
8586
deps = [ "$dir_pw_protobuf:common_protos" ]
8687
strip_prefix = "protos"
8788
prefix = "fabric_admin_service"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
chip.rpc.DeviceCommissioningWindowInfo.verifier max_size:97 // kSpake2p_VerifierSerialized_Length
2+
chip.rpc.DeviceCommissioningWindowInfo.salt max_size:32 // kSpake2p_Max_PBKDF_Salt_Length

examples/common/pigweed/protos/fabric_admin_service.proto

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import 'pw_protobuf_protos/common.proto';
55
package chip.rpc;
66

77
// Define the message for a synchronized end device with necessary fields
8-
message DeviceInfo {
8+
message DeviceCommissioningWindowInfo {
99
uint64 node_id = 1;
10+
uint32 commissioning_timeout = 2;
11+
uint32 discriminator = 3;
12+
uint32 iterations = 4;
13+
bytes salt = 5;
14+
bytes verifier = 6;
1015
}
1116

1217
// Define the response message to convey the status of the operation
@@ -15,6 +20,5 @@ message OperationStatus {
1520
}
1621

1722
service FabricAdmin {
18-
rpc OpenCommissioningWindow(DeviceInfo) returns (OperationStatus){}
23+
rpc OpenCommissioningWindow(DeviceCommissioningWindowInfo) returns (OperationStatus){}
1924
}
20-

examples/common/pigweed/rpc_services/FabricAdmin.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service<FabricAdmin>
3434
public:
3535
virtual ~FabricAdmin() = default;
3636

37-
virtual pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response)
37+
virtual pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response)
3838
{
3939
return pw::Status::Unimplemented();
4040
}

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

+5-9
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,13 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
3535
{
3636
CHIP_ERROR err = CHIP_NO_ERROR;
3737
SetupPayload ignored;
38-
const uint8_t payload[] = { 0x15, 0x36, 0x01, 0x15, 0x35, 0x01, 0x26, 0x00, 0x72, 0x4D, 0xDB, 0xCB,
39-
0x37, 0x01, 0x24, 0x02, 0x00, 0x24, 0x03, 0x1F, 0x24, 0x04, 0x00 };
40-
chip::ByteSpan payloadSpan(payload);
41-
chip::Optional<unsigned int> setupPIN(20202021);
42-
chip::Optional<chip::ByteSpan> salt(payloadSpan);
4338

4439
if (mEndpointId == kRootEndpointId)
4540
{
4641
err =
4742
mWindowOpener->OpenCommissioningWindow(mNodeId, System::Clock::Seconds16(mCommissioningWindowTimeout), mIteration,
48-
mDiscriminator, setupPIN, salt, &mOnOpenCommissioningWindowCallback, ignored,
49-
/* readVIDPIDAttributes */ true);
43+
mDiscriminator, chip::NullOptional, mVerifier, mSalt,
44+
&mOnOpenCommissioningWindowCallback, ignored, /* readVIDPIDAttributes */ true);
5045
}
5146
else
5247
{
@@ -56,8 +51,9 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
5651
.timeout = System::Clock::Seconds16(mCommissioningWindowTimeout),
5752
.iteration = mIteration,
5853
.discriminator = mDiscriminator,
59-
.setupPIN = setupPIN,
60-
.salt = salt,
54+
.setupPIN = chip::NullOptional,
55+
.verifier = mVerifier,
56+
.salt = mSalt,
6157
.callback = &mOnOpenCommissioningWindowCallback,
6258
};
6359

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

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class OpenCommissioningWindowCommand : public CHIPCommand
4747
&mIteration, "Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0.");
4848
AddArgument("discriminator", 0, 4096, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0.");
4949
AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out.");
50+
AddArgument("salt", &mSalt, "Salt payload encoded in hexadecimal. Random salt will be generated if absent");
51+
AddArgument("verifier", &mVerifier, "PAKE Passcode verifier encoded in hexadecimal format");
5052
}
5153

5254
void RegisterDelegate(CommissioningWindowDelegate * delegate) { mDelegate = delegate; }
@@ -67,6 +69,8 @@ class OpenCommissioningWindowCommand : public CHIPCommand
6769
uint16_t mCommissioningWindowTimeout;
6870
uint32_t mIteration;
6971
uint16_t mDiscriminator;
72+
chip::Optional<chip::ByteSpan> mSalt;
73+
chip::Optional<chip::ByteSpan> mVerifier;
7074

7175
chip::Optional<uint16_t> mTimeout;
7276

examples/fabric-admin/rpc/RpcServer.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,24 @@ namespace {
3737
class FabricAdmin final : public rpc::FabricAdmin
3838
{
3939
public:
40-
pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) override
40+
pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response) override
4141
{
4242
NodeId nodeId = request.node_id;
43+
uint32_t commissioningTimeout = request.commissioning_timeout;
44+
uint32_t iterations = request.iterations;
45+
uint32_t discriminator = request.discriminator;
46+
47+
char saltHex[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1];
48+
chip::Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), chip::Encoding::HexFlags::kNullTerminate);
49+
50+
char verifierHex[chip::Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1];
51+
chip::Encoding::BytesToHex(request.verifier.bytes, request.verifier.size, verifierHex, sizeof(verifierHex), chip::Encoding::HexFlags::kNullTerminate);
52+
4353
ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId);
4454

45-
char command[64];
46-
snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d", nodeId, kRootEndpointId,
47-
kEnhancedCommissioningMethod, kWindowTimeout, kIteration, kDiscriminator);
55+
char command[512];
56+
snprintf(command, sizeof(command), "pairing open-commissioning-window %ld %d %d %d %d %d --salt hex:%s --verifier hex:%s", nodeId, kRootEndpointId,
57+
kEnhancedCommissioningMethod, commissioningTimeout, iterations, discriminator, saltHex, verifierHex);
4858

4959
PushCommand(command);
5060

examples/fabric-bridge-app/linux/RpcClient.cpp

+26-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort)
9191
return rpc::client::StartPacketProcessing();
9292
}
9393

94-
CHIP_ERROR OpenCommissioningWindow(NodeId nodeId)
94+
CHIP_ERROR OpenCommissioningWindow(NodeId nodeId, uint16_t commissioningTimeout, uint16_t discriminator, uint32_t iterations,
95+
chip::Optional<chip::ByteSpan> salt, chip::Optional<chip::ByteSpan> verifier)
9596
{
9697
ChipLogProgress(NotSpecified, "OpenCommissioningWindow with Node Id 0x:" ChipLogFormatX64, ChipLogValueX64(nodeId));
9798

@@ -101,9 +102,32 @@ CHIP_ERROR OpenCommissioningWindow(NodeId nodeId)
101102
return CHIP_ERROR_BUSY;
102103
}
103104

104-
chip_rpc_DeviceInfo device;
105+
chip_rpc_DeviceCommissioningWindowInfo device;
105106
device.node_id = nodeId;
107+
device.commissioning_timeout = commissioningTimeout;
108+
device.discriminator = discriminator;
109+
device.iterations = iterations;
106110

111+
if (salt.HasValue())
112+
{
113+
if (salt.Value().size() > sizeof(device.salt.bytes))
114+
{
115+
return CHIP_ERROR_INTERNAL;
116+
}
117+
memcpy(device.salt.bytes, salt.Value().data(), salt.Value().size());
118+
device.salt.size = static_cast<pb_size_t>(salt.Value().size());
119+
}
120+
121+
if (salt.HasValue())
122+
{
123+
if (verifier.Value().size() > sizeof(device.verifier.bytes))
124+
{
125+
return CHIP_ERROR_INTERNAL;
126+
}
127+
memcpy(device.verifier.bytes, verifier.Value().data(), verifier.Value().size());
128+
device.verifier.size = static_cast<pb_size_t>(verifier.Value().size());
129+
}
130+
107131
// The RPC will remain active as long as `openCommissioningWindowCall` is alive.
108132
openCommissioningWindowCall = fabricAdminClient.OpenCommissioningWindow(device, OnOpenCommissioningWindowCompleted);
109133

examples/fabric-bridge-app/linux/include/RpcClient.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort);
4141
* - CHIP_ERROR_BUSY: Another commissioning window is currently in progress.
4242
* - CHIP_ERROR_INTERNAL: An internal error occurred.
4343
*/
44-
CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId);
44+
CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId, uint16_t commissioningTimeout,
45+
uint16_t discriminator, uint32_t iterations, chip::Optional<chip::ByteSpan> salt,
46+
chip::Optional<chip::ByteSpan> verifier);

examples/fabric-bridge-app/linux/main.cpp

+27-7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void BridgePollingThread()
7474
#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
7575
else if (ch == 'o')
7676
{
77-
CHIP_ERROR err = OpenCommissioningWindow(0x1234);
77+
CHIP_ERROR err = OpenCommissioningWindow(0x1234, 300, 3840, 1000, chip::NullOptional, chip::NullOptional);
7878
if (err != CHIP_NO_ERROR)
7979
{
8080
ChipLogError(NotSpecified, "Failed to call OpenCommissioningWindow RPC: %" CHIP_ERROR_FORMAT, err.Format());
@@ -128,26 +128,46 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha
128128
return;
129129
}
130130

131+
uint16_t commissioningTimeout;
132+
chip::Optional<chip::ByteSpan> pakeVerifier;
133+
uint16_t discriminator;
134+
uint32_t iterations;
135+
chip::Optional<chip::ByteSpan> salt;
136+
Device * device = nullptr;
137+
Status status = Status::Failure;
138+
139+
Commands::OpenCommissioningWindow::DecodableType commandData;
140+
CHIP_ERROR tlvError = DataModel::Decode(handlerContext.mPayload, commandData);
141+
SuccessOrExit(tlvError);
142+
143+
commissioningTimeout = commandData.commissioningTimeout;
144+
pakeVerifier = chip::Optional<chip::ByteSpan>(commandData.PAKEPasscodeVerifier);
145+
discriminator = commandData.discriminator;
146+
iterations = commandData.iterations;
147+
salt = chip::Optional<chip::ByteSpan>(commandData.salt);
148+
ChipLogProgress(NotSpecified, "Proxying OCW with discriminator %d and iterations %d", discriminator, iterations);
149+
131150
handlerContext.SetCommandHandled();
132-
Status status = Status::Success;
133151

134152
#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
135-
Device * device = DeviceMgr().GetDevice(endpointId);
136-
137-
if (device != nullptr && OpenCommissioningWindow(device->GetNodeId()) == CHIP_NO_ERROR)
153+
device = DeviceMgr().GetDevice(endpointId);
154+
if (device != nullptr &&
155+
OpenCommissioningWindow(device->GetNodeId(), commissioningTimeout, discriminator, iterations, salt, pakeVerifier) ==
156+
CHIP_NO_ERROR)
138157
{
139158
ChipLogProgress(NotSpecified, "Commissioning window is now open");
159+
status = Status::Success;
140160
}
141161
else
142162
{
143-
status = Status::Failure;
144-
ChipLogProgress(NotSpecified, "Commissioning window is failed to open");
163+
ChipLogError(NotSpecified, "Commissioning window is failed to open");
145164
}
146165
#else
147166
status = Status::Failure;
148167
ChipLogProgress(NotSpecified, "Commissioning window failed to open: PW_RPC_FABRIC_BRIDGE_SERVICE not defined");
149168
#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
150169

170+
exit:
151171
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
152172
}
153173

src/controller/CommissioningWindowOpener.cpp

+16-7
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId device
5555
}
5656

5757
CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, Seconds16 timeout, uint32_t iteration,
58-
uint16_t discriminator, Optional<uint32_t> setupPIN,
59-
Optional<ByteSpan> salt,
58+
uint16_t discriminator, Optional<uint32_t> setupPIN,
59+
Optional<ByteSpan> verifier, Optional<ByteSpan> salt,
6060
Callback::Callback<OnOpenCommissioningWindow> * callback,
6161
SetupPayload & payload, bool readVIDPIDAttributes)
6262
{
@@ -67,6 +67,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, S
6767
.iteration = iteration,
6868
.discriminator = discriminator,
6969
.setupPIN = setupPIN,
70+
.verifier = verifier,
7071
.salt = salt,
7172
.callback = callback,
7273
};
@@ -130,9 +131,17 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowImpl(const Commissi
130131
mCommissioningWindowTimeout = params.timeout;
131132
mPBKDFIterations = params.iteration;
132133

133-
bool randomSetupPIN = !params.setupPIN.HasValue();
134-
ReturnErrorOnFailure(
135-
PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
134+
if (params.verifier.HasValue())
135+
{
136+
ChipLogProgress(NotSpecified, "Verifier size is %ld", params.verifier.Value().size());
137+
ReturnErrorOnFailure(mVerifier.Deserialize(params.verifier.Value()));
138+
}
139+
else
140+
{
141+
bool randomSetupPIN = !params.setupPIN.HasValue();
142+
ReturnErrorOnFailure(
143+
PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
144+
}
136145

137146
payload = mSetupPayload;
138147

@@ -376,8 +385,8 @@ CHIP_ERROR AutoCommissioningWindowOpener::OpenCommissioningWindow(DeviceControll
376385
}
377386

378387
CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
379-
deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
380-
readVIDPIDAttributes);
388+
deviceId, timeout, iteration, discriminator, setupPIN, chip::NullOptional, salt, &opener->mOnOpenCommissioningWindowCallback,
389+
payload, readVIDPIDAttributes);
381390
if (err != CHIP_NO_ERROR)
382391
{
383392
delete opener;

src/controller/CommissioningWindowOpener.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class CommissioningWindowOpener
5151
// verifier to be used for this commissioning.
5252
uint16_t discriminator; // The long discriminator for the DNS-SD advertisement.
5353
Optional<uint32_t> setupPIN; // The setup PIN to use, or NullOptional to use a randomly-generated one.
54+
Optional<ByteSpan> verifier; // The PAKE passcode verifier, if provided, will be used instead of generating one from setup PIN code
5455
Optional<ByteSpan> salt; // The salt to use, or NullOptional to use a randomly-generated one. If provided, must be at least
5556
// kSpake2p_Min_PBKDF_Salt_Length bytes and at most kSpake2p_Max_PBKDF_Salt_Length bytes in length.
5657
Callback::Callback<OnOpenCommissioningWindow> *
@@ -99,6 +100,8 @@ class CommissioningWindowOpener
99100
* PAKE passcode verifier to be used for this commissioning.
100101
* @param[in] discriminator The long discriminator for the DNS-SD advertisement.
101102
* @param[in] setupPIN The setup PIN to use, or NullOptional to use a randomly-generated one.
103+
* @param[in] verifier The PAKE passcode verifier to use, or NullOptional to
104+
* generate verifier based on PIN and other parameters.
102105
* @param[in] salt The salt to use, or NullOptional to use a
103106
* randomly-generated one. If provided, must be at
104107
* least kSpake2p_Min_PBKDF_Salt_Length bytes and
@@ -118,9 +121,9 @@ class CommissioningWindowOpener
118121
* callback.
119122
*/
120123
CHIP_ERROR OpenCommissioningWindow(NodeId deviceId, System::Clock::Seconds16 timeout, uint32_t iteration,
121-
uint16_t discriminator, Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
122-
Callback::Callback<OnOpenCommissioningWindow> * callback, SetupPayload & payload,
123-
bool readVIDPIDAttributes = false);
124+
uint16_t discriminator, Optional<uint32_t> setupPIN, Optional<ByteSpan> verifier,
125+
Optional<ByteSpan> salt, Callback::Callback<OnOpenCommissioningWindow> * callback,
126+
SetupPayload & payload, bool readVIDPIDAttributes = false);
124127

125128
/**
126129
* @brief

0 commit comments

Comments
 (0)