Skip to content

Commit

Permalink
Update RPC and Add verifier to CommissioningWindowOpener
Browse files Browse the repository at this point in the history
  • Loading branch information
samadDotDev committed Jun 19, 2024
1 parent 6bc96df commit f205ff2
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 34 deletions.
1 change: 1 addition & 0 deletions examples/common/pigweed/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pw_proto_library("button_service") {

pw_proto_library("fabric_admin_service") {
sources = [ "protos/fabric_admin_service.proto" ]
inputs = [ "protos/fabric_admin_service.options" ]
deps = [ "$dir_pw_protobuf:common_protos" ]
strip_prefix = "protos"
prefix = "fabric_admin_service"
Expand Down
2 changes: 2 additions & 0 deletions examples/common/pigweed/protos/fabric_admin_service.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
chip.rpc.DeviceCommissioningWindowInfo.verifier max_size:97 // kSpake2p_VerifierSerialized_Length
chip.rpc.DeviceCommissioningWindowInfo.salt max_size:32 // kSpake2p_Max_PBKDF_Salt_Length
10 changes: 7 additions & 3 deletions examples/common/pigweed/protos/fabric_admin_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import 'pw_protobuf_protos/common.proto';
package chip.rpc;

// Define the message for a synchronized end device with necessary fields
message DeviceInfo {
message DeviceCommissioningWindowInfo {
uint64 node_id = 1;
uint32 commissioning_timeout = 2;
uint32 discriminator = 3;
uint32 iterations = 4;
bytes salt = 5;
bytes verifier = 6;
}

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

service FabricAdmin {
rpc OpenCommissioningWindow(DeviceInfo) returns (OperationStatus){}
rpc OpenCommissioningWindow(DeviceCommissioningWindowInfo) returns (OperationStatus){}
}

2 changes: 1 addition & 1 deletion examples/common/pigweed/rpc_services/FabricAdmin.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service<FabricAdmin>
public:
virtual ~FabricAdmin() = default;

virtual pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response)
virtual pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response)
{
return pw::Status::Unimplemented();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,13 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
{
CHIP_ERROR err = CHIP_NO_ERROR;
SetupPayload ignored;
const uint8_t payload[] = { 0x15, 0x36, 0x01, 0x15, 0x35, 0x01, 0x26, 0x00, 0x72, 0x4D, 0xDB, 0xCB,
0x37, 0x01, 0x24, 0x02, 0x00, 0x24, 0x03, 0x1F, 0x24, 0x04, 0x00 };
chip::ByteSpan payloadSpan(payload);
chip::Optional<unsigned int> setupPIN(20202021);
chip::Optional<chip::ByteSpan> salt(payloadSpan);

if (mEndpointId == kRootEndpointId)
{
err =
mWindowOpener->OpenCommissioningWindow(mNodeId, System::Clock::Seconds16(mCommissioningWindowTimeout), mIteration,
mDiscriminator, setupPIN, salt, &mOnOpenCommissioningWindowCallback, ignored,
/* readVIDPIDAttributes */ true);
mDiscriminator, chip::NullOptional, mVerifier, mSalt,
&mOnOpenCommissioningWindowCallback, ignored, /* readVIDPIDAttributes */ true);
}
else
{
Expand All @@ -56,8 +51,9 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
.timeout = System::Clock::Seconds16(mCommissioningWindowTimeout),
.iteration = mIteration,
.discriminator = mDiscriminator,
.setupPIN = setupPIN,
.salt = salt,
.setupPIN = chip::NullOptional,
.verifier = mVerifier,
.salt = mSalt,
.callback = &mOnOpenCommissioningWindowCallback,
};

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

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

chip::Optional<uint16_t> mTimeout;

Expand Down
18 changes: 14 additions & 4 deletions examples/fabric-admin/rpc/RpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,24 @@ namespace {
class FabricAdmin final : public rpc::FabricAdmin
{
public:
pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) override
pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response) override
{
NodeId nodeId = request.node_id;
uint32_t commissioningTimeout = request.commissioning_timeout;
uint32_t iterations = request.iterations;
uint32_t discriminator = request.discriminator;

char saltHex[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1];
chip::Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), chip::Encoding::HexFlags::kNullTerminate);

char verifierHex[chip::Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1];
chip::Encoding::BytesToHex(request.verifier.bytes, request.verifier.size, verifierHex, sizeof(verifierHex), chip::Encoding::HexFlags::kNullTerminate);

ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId);

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

PushCommand(command);

Expand Down
28 changes: 26 additions & 2 deletions examples/fabric-bridge-app/linux/RpcClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort)
return rpc::client::StartPacketProcessing();
}

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

Expand All @@ -101,9 +102,32 @@ CHIP_ERROR OpenCommissioningWindow(NodeId nodeId)
return CHIP_ERROR_BUSY;
}

chip_rpc_DeviceInfo device;
chip_rpc_DeviceCommissioningWindowInfo device;
device.node_id = nodeId;
device.commissioning_timeout = commissioningTimeout;
device.discriminator = discriminator;
device.iterations = iterations;

if (salt.HasValue())
{
if (salt.Value().size() > sizeof(device.salt.bytes))
{
return CHIP_ERROR_INTERNAL;
}
memcpy(device.salt.bytes, salt.Value().data(), salt.Value().size());
device.salt.size = static_cast<pb_size_t>(salt.Value().size());
}

if (salt.HasValue())
{
if (verifier.Value().size() > sizeof(device.verifier.bytes))
{
return CHIP_ERROR_INTERNAL;
}
memcpy(device.verifier.bytes, verifier.Value().data(), verifier.Value().size());
device.verifier.size = static_cast<pb_size_t>(verifier.Value().size());
}

// The RPC will remain active as long as `openCommissioningWindowCall` is alive.
openCommissioningWindowCall = fabricAdminClient.OpenCommissioningWindow(device, OnOpenCommissioningWindowCompleted);

Expand Down
4 changes: 3 additions & 1 deletion examples/fabric-bridge-app/linux/include/RpcClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort);
* - CHIP_ERROR_BUSY: Another commissioning window is currently in progress.
* - CHIP_ERROR_INTERNAL: An internal error occurred.
*/
CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId);
CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId, uint16_t commissioningTimeout,
uint16_t discriminator, uint32_t iterations, chip::Optional<chip::ByteSpan> salt,
chip::Optional<chip::ByteSpan> verifier);
9 changes: 5 additions & 4 deletions examples/fabric-bridge-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ void BridgePollingThread()
#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
else if (ch == 'o')
{
CHIP_ERROR err = OpenCommissioningWindow(0x1234);
commissioningTimeout, discriminator, iterations, salt, pakeVerifier
CHIP_ERROR err = OpenCommissioningWindow(0x1234, 300, 3840, 1000, chip::NullOptional, chip::NullOptional);
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to call OpenCommissioningWindow RPC: %" CHIP_ERROR_FORMAT, err.Format());
Expand Down Expand Up @@ -125,7 +126,7 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha
return;
}

chip::System::Clock::Seconds16 commissioningTimeout;
uint16_t commissioningTimeout;
chip::ByteSpan pakeVerifier;
uint16_t discriminator;
uint32_t iterations;
Expand All @@ -138,7 +139,7 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha
CHIP_ERROR tlvError = DataModel::Decode(handlerContext.mPayload, commandData);
SuccessOrExit(tlvError);

commissioningTimeout = System::Clock::Seconds16(commandData.commissioningTimeout);
commissioningTimeout = commandData.commissioningTimeout;
pakeVerifier = commandData.PAKEPasscodeVerifier;
discriminator = commandData.discriminator;
iterations = commandData.iterations;
Expand All @@ -149,7 +150,7 @@ void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & ha

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
device = DeviceMgr().GetDevice(endpointId);
if (device != nullptr && OpenCommissioningWindow(device->GetNodeId()) == CHIP_NO_ERROR)
if (device != nullptr && OpenCommissioningWindow(device->GetNodeId(), commissioningTimeout, discriminator, iterations, salt, pakeVerifier) == CHIP_NO_ERROR)
{
ChipLogProgress(NotSpecified, "Commissioning window is now open");
status = Status::Success;
Expand Down
23 changes: 16 additions & 7 deletions src/controller/CommissioningWindowOpener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId device
}

CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, Seconds16 timeout, uint32_t iteration,
uint16_t discriminator, Optional<uint32_t> setupPIN,
Optional<ByteSpan> salt,
uint16_t discriminator, Optional<uint32_t> setupPIN,
Optional<ByteSpan> verifier, Optional<ByteSpan> salt,
Callback::Callback<OnOpenCommissioningWindow> * callback,
SetupPayload & payload, bool readVIDPIDAttributes)
{
Expand All @@ -67,6 +67,7 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, S
.iteration = iteration,
.discriminator = discriminator,
.setupPIN = setupPIN,
.verifier = verifier,
.salt = salt,
.callback = callback,
};
Expand Down Expand Up @@ -130,9 +131,17 @@ CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowImpl(const Commissi
mCommissioningWindowTimeout = params.timeout;
mPBKDFIterations = params.iteration;

bool randomSetupPIN = !params.setupPIN.HasValue();
ReturnErrorOnFailure(
PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
if (params.verifier.HasValue())
{
ChipLogProgress(NotSpecified, "Verifier size is %ld", params.verifier.Value().size());
ReturnErrorOnFailure(mVerifier.Deserialize(params.verifier.Value()));
}
else
{
bool randomSetupPIN = !params.setupPIN.HasValue();
ReturnErrorOnFailure(
PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
}

payload = mSetupPayload;

Expand Down Expand Up @@ -376,8 +385,8 @@ CHIP_ERROR AutoCommissioningWindowOpener::OpenCommissioningWindow(DeviceControll
}

CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
readVIDPIDAttributes);
deviceId, timeout, iteration, discriminator, setupPIN, chip::NullOptional, salt, &opener->mOnOpenCommissioningWindowCallback,
payload, readVIDPIDAttributes);
if (err != CHIP_NO_ERROR)
{
delete opener;
Expand Down
9 changes: 6 additions & 3 deletions src/controller/CommissioningWindowOpener.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class CommissioningWindowOpener
// verifier to be used for this commissioning.
uint16_t discriminator; // The long discriminator for the DNS-SD advertisement.
Optional<uint32_t> setupPIN; // The setup PIN to use, or NullOptional to use a randomly-generated one.
Optional<ByteSpan> verifier; // The PAKE passcode verifier, if provided, will be used instead of generating one from setup PIN code
Optional<ByteSpan> salt; // The salt to use, or NullOptional to use a randomly-generated one. If provided, must be at least
// kSpake2p_Min_PBKDF_Salt_Length bytes and at most kSpake2p_Max_PBKDF_Salt_Length bytes in length.
Callback::Callback<OnOpenCommissioningWindow> *
Expand Down Expand Up @@ -99,6 +100,8 @@ class CommissioningWindowOpener
* PAKE passcode verifier to be used for this commissioning.
* @param[in] discriminator The long discriminator for the DNS-SD advertisement.
* @param[in] setupPIN The setup PIN to use, or NullOptional to use a randomly-generated one.
* @param[in] verifier The PAKE passcode verifier to use, or NullOptional to
* generate verifier based on PIN and other parameters.
* @param[in] salt The salt to use, or NullOptional to use a
* randomly-generated one. If provided, must be at
* least kSpake2p_Min_PBKDF_Salt_Length bytes and
Expand All @@ -118,9 +121,9 @@ class CommissioningWindowOpener
* callback.
*/
CHIP_ERROR OpenCommissioningWindow(NodeId deviceId, System::Clock::Seconds16 timeout, uint32_t iteration,
uint16_t discriminator, Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
Callback::Callback<OnOpenCommissioningWindow> * callback, SetupPayload & payload,
bool readVIDPIDAttributes = false);
uint16_t discriminator, Optional<uint32_t> setupPIN, Optional<ByteSpan> verifier,
Optional<ByteSpan> salt, Callback::Callback<OnOpenCommissioningWindow> * callback,
SetupPayload & payload, bool readVIDPIDAttributes = false);

/**
* @brief
Expand Down

0 comments on commit f205ff2

Please sign in to comment.