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-Admin] Refactor to use API methods instead of PushCommand (1/3) #35614

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions examples/fabric-admin/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ static_library("fabric-admin-utils") {
"device_manager/DeviceSubscriptionManager.h",
"device_manager/DeviceSynchronization.cpp",
"device_manager/DeviceSynchronization.h",
"device_manager/PairingManager.cpp",
"device_manager/PairingManager.h",
"device_manager/UniqueIdGetter.cpp",
"device_manager/UniqueIdGetter.h",
]
Expand Down
3 changes: 3 additions & 0 deletions examples/fabric-admin/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "IcdManager.h"
#include <controller/CHIPDeviceControllerFactory.h>
#include <credentials/attestation_verifier/FileAttestationTrustStore.h>
#include <device_manager/PairingManager.h>
#include <lib/core/CHIPConfig.h>
#include <lib/core/CHIPVendorIdentifiers.hpp>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -181,6 +182,8 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey,
allowTestCdSigningKey);

ReturnLogErrorOnFailure(PairingManager::Instance().Init(&CurrentCommissioner()));

return CHIP_NO_ERROR;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,7 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId)
return CHIP_NO_ERROR;
}

OpenCommissioningWindowCommand * openCommand =
static_cast<OpenCommissioningWindowCommand *>(CommandMgr().GetCommandByName("pairing", "open-commissioning-window"));

if (openCommand == nullptr)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

openCommand->RegisterDelegate(this);
PairingManager::Instance().RegisterOpenCommissioningWindowDelegate(this);

DeviceMgr().OpenRemoteDeviceCommissioningWindow(remoteId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#pragma once

#include <commands/common/CHIPCommand.h>
#include <commands/pairing/OpenCommissioningWindowCommand.h>
#include <commands/pairing/PairingCommand.h>
#include <device_manager/PairingManager.h>

// Constants
constexpr uint32_t kCommissionPrepareTimeMs = 500;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,6 @@ CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
void OpenCommissioningWindowCommand::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err,
chip::SetupPayload payload)
{
OpenCommissioningWindowCommand * self = static_cast<OpenCommissioningWindowCommand *>(context);
if (self->mDelegate)
{
self->mDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
self->UnregisterDelegate();
}

LogErrorOnFailure(err);
OnOpenBasicCommissioningWindowResponse(context, remoteId, err);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@
#include <controller/CommissioningWindowOpener.h>
#include <lib/support/CHIPMem.h>

class CommissioningWindowDelegate
{
public:
virtual void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) = 0;
virtual ~CommissioningWindowDelegate() = default;
};

class OpenCommissioningWindowCommand : public CHIPCommand
{
public:
Expand Down Expand Up @@ -57,9 +50,6 @@ class OpenCommissioningWindowCommand : public CHIPCommand
"params if absent");
}

void RegisterDelegate(CommissioningWindowDelegate * delegate) { mDelegate = delegate; }
void UnregisterDelegate() { mDelegate = nullptr; }

/////////// CHIPCommand Interface /////////
CHIP_ERROR RunCommand() override;

Expand All @@ -71,7 +61,6 @@ class OpenCommissioningWindowCommand : public CHIPCommand
NodeId mNodeId;
chip::EndpointId mEndpointId;
chip::Controller::CommissioningWindowOpener::CommissioningWindowOption mCommissioningWindowOption;
CommissioningWindowDelegate * mDelegate = nullptr;
uint16_t mCommissioningWindowTimeout;
uint32_t mIteration;
uint16_t mDiscriminator;
Expand Down
60 changes: 29 additions & 31 deletions examples/fabric-admin/device_manager/DeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <commands/interactive/InteractiveCommands.h>
#include <crypto/RandUtils.h>
#include <device_manager/PairingManager.h>
#include <lib/support/StringBuilder.h>

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

namespace {

constexpr uint16_t kWindowTimeout = 300;
constexpr uint16_t kIteration = 1000;
constexpr uint16_t kSubscribeMinInterval = 0;
constexpr uint16_t kSubscribeMaxInterval = 60;
constexpr uint16_t kAggragatorEndpointId = 1;
constexpr uint16_t kMaxDiscriminatorLength = 4095;
constexpr uint8_t kEnhancedCommissioningMethod = 1;
constexpr uint16_t kWindowTimeout = 300;
constexpr uint16_t kIteration = 1000;
constexpr uint16_t kSubscribeMinInterval = 0;
constexpr uint16_t kSubscribeMaxInterval = 60;
constexpr uint16_t kAggragatorEndpointId = 1;
constexpr uint16_t kMaxDiscriminatorLength = 4095;

} // namespace

Expand Down Expand Up @@ -116,18 +116,17 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId)
}

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

// Open the commissioning window of a device within its own fabric.
StringBuilder<kMaxCommandSize> commandBuilder;

commandBuilder.Add("pairing open-commissioning-window ");
commandBuilder.AddFormat("%lu %d %d %d %d %d --salt hex:%s --verifier hex:%s", nodeId, kRootEndpointId,
kEnhancedCommissioningMethod, commissioningTimeout, iterations, discriminator, saltHex, verifierHex);

PushCommand(commandBuilder.c_str());
CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(nodeId, kRootEndpointId, commissioningTimeout, iterations,
discriminator, salt, verifier);
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err));
}
}

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

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

PushCommand(commandBuilder.c_str());
CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(mRemoteBridgeNodeId, remoteEndpointId, kWindowTimeout,
kIteration, discriminator, emptySalt, emptyVerifier);
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err));
}
}

void DeviceManager::PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp,
Expand Down Expand Up @@ -421,6 +424,7 @@ void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data)
{
CommissionerControl::Commands::ReverseOpenCommissioningWindow::DecodableType value;
CHIP_ERROR error = app::DataModel::Decode(data, value);

if (error != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format());
Expand All @@ -432,18 +436,12 @@ void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data)
ChipLogProgress(NotSpecified, " commissioningTimeout: %u", value.commissioningTimeout);
ChipLogProgress(NotSpecified, " discriminator: %u", value.discriminator);
ChipLogProgress(NotSpecified, " iterations: %u", value.iterations);
ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier size: %lu", value.PAKEPasscodeVerifier.size());
ChipLogProgress(NotSpecified, " salt size: %lu", value.salt.size());

char verifierHex[Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1];
Encoding::BytesToHex(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size(), verifierHex, sizeof(verifierHex),
Encoding::HexFlags::kNullTerminate);
ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier: %s", verifierHex);

char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1];
Encoding::BytesToHex(value.salt.data(), value.salt.size(), saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate);
ChipLogProgress(NotSpecified, " salt: %s", saltHex);

OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator, saltHex,
verifierHex);
OpenDeviceCommissioningWindow(mLocalBridgeNodeId, value.commissioningTimeout, value.iterations, value.discriminator,
ByteSpan(value.salt.data(), value.salt.size()),
ByteSpan(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size()));
}

void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader & data)
Expand Down
6 changes: 3 additions & 3 deletions examples/fabric-admin/device_manager/DeviceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ class DeviceManager : public PairingDelegate
* for deriving the PAKE (Password Authenticated Key Exchange) verifier.
* @param discriminator The device-specific discriminator, determined during commissioning, which helps
* to uniquely identify the device among others.
* @param saltHex The hexadecimal-encoded salt used in the cryptographic operations for commissioning.
* @param verifierHex The hexadecimal-encoded PAKE verifier used to authenticate the commissioning process.
* @param salt The salt used in the cryptographic operations for commissioning.
* @param verifier The PAKE verifier used to authenticate the commissioning process.
*
*/
void OpenDeviceCommissioningWindow(chip::NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations,
uint32_t discriminator, const char * saltHex, const char * verifierHex);
uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier);

/**
* @brief Open the commissioning window of a device from another fabric via its fabric bridge.
Expand Down
147 changes: 147 additions & 0 deletions examples/fabric-admin/device_manager/PairingManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "PairingManager.h"

#include <controller/CommissioningDelegate.h>
#include <controller/CurrentFabricRemover.h>
#include <lib/support/Span.h>

using namespace ::chip;

Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> PairingManager::mWindowOpener;

PairingManager::PairingManager() :
mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
mOnOpenCommissioningWindowVerifierCallback(OnOpenCommissioningWindowVerifierResponse, this)
{}

CHIP_ERROR PairingManager::Init(chip::Controller::DeviceCommissioner * commissioner)
{
mCommissioner = commissioner;
return CHIP_NO_ERROR;
}

CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId endpointId, uint16_t commissioningTimeout,
uint32_t iterations, uint16_t discriminator, const ByteSpan & salt,
const ByteSpan & verifier)
{
VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);

auto * params = new CommissioningWindowParams();
params->nodeId = nodeId;
params->endpointId = endpointId;
params->commissioningWindowTimeout = commissioningTimeout;
params->iteration = iterations;
params->discriminator = discriminator;

if (!salt.empty())
{
memcpy(params->saltBuffer, salt.data(), salt.size());
params->salt = ByteSpan(params->saltBuffer, salt.size());
}

if (!verifier.empty())
{
memcpy(params->verifierBuffer, verifier.data(), verifier.size());
params->verifier = ByteSpan(params->verifierBuffer, verifier.size());
}

// Schedule work on the Matter thread
chip::DeviceLayer::PlatformMgr().ScheduleWork(OnOpenCommissioningWindow, reinterpret_cast<intptr_t>(params));

return CHIP_NO_ERROR;
}

void PairingManager::OnOpenCommissioningWindow(intptr_t context)
{
auto * params = reinterpret_cast<CommissioningWindowParams *>(context);
PairingManager & self = PairingManager::Instance();

if (self.mCommissioner == nullptr)
{
ChipLogError(AppServer, "Commissioner is null, cannot open commissioning window");
return;
}

mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(self.mCommissioner);

if (!params->verifier.empty())
{
if (params->salt.empty())
{
ChipLogError(AppServer, "Salt is required when verifier is set");
return;
}

CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams()
.SetNodeId(params->nodeId)
.SetEndpointId(params->endpointId)
.SetTimeout(params->commissioningWindowTimeout)
.SetIteration(params->iteration)
.SetDiscriminator(params->discriminator)
.SetVerifier(params->verifier)
.SetSalt(params->salt)
.SetCallback(&self.mOnOpenCommissioningWindowVerifierCallback));
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Failed to open commissioning window with verifier: %s", ErrorStr(err));
}
}
else
{
SetupPayload ignored;
CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
.SetNodeId(params->nodeId)
.SetEndpointId(params->endpointId)
.SetTimeout(params->commissioningWindowTimeout)
.SetIteration(params->iteration)
.SetDiscriminator(params->discriminator)
.SetSetupPIN(NullOptional)
.SetSalt(NullOptional)
.SetCallback(&self.mOnOpenCommissioningWindowCallback),
ignored);
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Failed to open commissioning window with passcode: %s", ErrorStr(err));
}
}

// Clean up params
delete params;
}

void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, chip::SetupPayload payload)
{
PairingManager * self = static_cast<PairingManager *>(context);
if (self->mCommissioningWindowDelegate)
{
self->mCommissioningWindowDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
self->UnregisterOpenCommissioningWindowDelegate();
}

OnOpenCommissioningWindowVerifierResponse(context, remoteId, err);
}

void PairingManager::OnOpenCommissioningWindowVerifierResponse(void * context, NodeId remoteId, CHIP_ERROR err)
{
LogErrorOnFailure(err);

PairingManager * self = reinterpret_cast<PairingManager *>(context);
VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnOpenCommissioningWindowCommand: context is null"));
}
Loading
Loading