Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fabric-Bridge] Add state machine to CommissionerControlDelegate to guard various unexpected commands #35186

Merged
merged 4 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions examples/fabric-bridge-app/linux/CommissionerControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,33 @@ namespace app {
namespace Clusters {
namespace CommissionerControl {

void CommissionerControlDelegate::ResetDelegateState()
{
// Reset the step to the initial state
mNextStep = Step::kIdle;

// Reset identifiers and product information
mRequestId = 0;
mClientNodeId = kUndefinedNodeId;
mVendorId = VendorId::Unspecified;
mProductId = 0;

// Clear the label buffer and optional label
memset(mLabelBuffer, 0, sizeof(mLabelBuffer));
mLabel.ClearValue();

// Reset PBKDF salt and PAKE passcode verifier buffers
mPBKDFSalt = ByteSpan();
memset(mPBKDFSaltBuffer, 0, sizeof(mPBKDFSaltBuffer));

mPAKEPasscodeVerifier = ByteSpan();
memset(mPAKEPasscodeVerifierBuffer, 0, sizeof(mPAKEPasscodeVerifierBuffer));
}

CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request)
{
VerifyOrReturnError(mNextStep == Step::kIdle, CHIP_ERROR_INCORRECT_STATE);

CommissionerControl::Events::CommissioningRequestResult::Type result;
result.requestId = request.requestId;
result.clientNodeId = request.clientNodeId;
Expand Down Expand Up @@ -86,19 +111,34 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const
mLabel.ClearValue();
}

return CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(result);
CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(result);

if (err == CHIP_NO_ERROR)
{
mNextStep = Step::kWaitCommissionNodeRequest;
}
else
{
ResetDelegateState();
}

return err;
}

CHIP_ERROR CommissionerControlDelegate::ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId)
{
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrReturnError(mNextStep == Step::kWaitCommissionNodeRequest, CHIP_ERROR_INCORRECT_STATE);

// Verify if the CommissionNode command is sent from the same NodeId as the RequestCommissioningApproval.
VerifyOrExit(mClientNodeId == clientNodeId, err = CHIP_ERROR_WRONG_NODE_ID);

// Verify if the provided RequestId matches the value provided to the RequestCommissioningApproval.
VerifyOrExit(mRequestId == requestId, err = CHIP_ERROR_INCORRECT_STATE);

mNextStep = Step::kStartCommissionNode;

exit:
return err;
}
Expand Down Expand Up @@ -129,20 +169,29 @@ CHIP_ERROR CommissionerControlDelegate::GetCommissioningWindowParams(Commissioni
CHIP_ERROR CommissionerControlDelegate::HandleCommissionNode(const CommissioningWindowParams & params,
const Optional<ByteSpan> & ipAddress, const Optional<uint16_t> & port)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogProgress(NotSpecified, "CommissionerControlDelegate::HandleCommissionNode");

VerifyOrReturnError(mNextStep == Step::kStartCommissionNode, CHIP_ERROR_INCORRECT_STATE);

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
return CommissionNode(Controller::CommissioningWindowPasscodeParams()
.SetSetupPIN(kSetupPinCode)
.SetTimeout(params.commissioningTimeout)
.SetDiscriminator(params.discriminator)
.SetIteration(params.iterations)
.SetSalt(params.salt),
mVendorId, mProductId);
err = CommissionNode(Controller::CommissioningWindowPasscodeParams()
.SetSetupPIN(kSetupPinCode)
.SetTimeout(params.commissioningTimeout)
.SetDiscriminator(params.discriminator)
.SetIteration(params.iterations)
.SetSalt(params.salt),
mVendorId, mProductId);
#else
ChipLogProgress(NotSpecified, "Failed to reverse commission bridge: PW_RPC_FABRIC_BRIDGE_SERVICE not defined");
return CHIP_ERROR_NOT_IMPLEMENTED;
err = CHIP_ERROR_NOT_IMPLEMENTED;
#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE

// Reset the delegate's state to prepare for a new commissioning sequence.
ResetDelegateState();

return err;
}

} // namespace CommissionerControl
Expand Down
13 changes: 13 additions & 0 deletions examples/fabric-bridge-app/linux/include/CommissionerControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,21 @@ class CommissionerControlDelegate : public Delegate
~CommissionerControlDelegate() = default;

private:
enum class Step : uint8_t
{
// Ready to start reverse commissioning.
kIdle,
// Wait for the commission node command.
kWaitCommissionNodeRequest,
// Need to commission node.
kStartCommissionNode,
};

void ResetDelegateState();

static constexpr size_t kLabelBufferSize = 64;

Step mNextStep = Step::kIdle;
uint64_t mRequestId = 0;
NodeId mClientNodeId = kUndefinedNodeId;
VendorId mVendorId = VendorId::Unspecified;
Expand Down
Loading