diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index d1add205f8826c..ab584459582657 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -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", ] diff --git a/examples/fabric-admin/commands/common/CHIPCommand.cpp b/examples/fabric-admin/commands/common/CHIPCommand.cpp index 0c5455439b22d9..b18eb9f2de472a 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.cpp +++ b/examples/fabric-admin/commands/common/CHIPCommand.cpp @@ -21,6 +21,7 @@ #include "IcdManager.h" #include #include +#include #include #include #include @@ -181,6 +182,8 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey, allowTestCdSigningKey); + PairingManager::Instance().Init(&CurrentCommissioner()); + return CHIP_NO_ERROR; } diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 85a3aada9f88ae..64d43cce11f3ac 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -344,15 +344,7 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId) return CHIP_NO_ERROR; } - OpenCommissioningWindowCommand * openCommand = - static_cast(CommandMgr().GetCommandByName("pairing", "open-commissioning-window")); - - if (openCommand == nullptr) - { - return CHIP_ERROR_NOT_IMPLEMENTED; - } - - openCommand->RegisterDelegate(this); + PairingManager::Instance().SetOpenCommissioningWindowDelegate(this); DeviceMgr().OpenRemoteDeviceCommissioningWindow(remoteId); diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h index 669edd75d653e6..e80f10133853f7 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h @@ -19,8 +19,8 @@ #pragma once #include -#include #include +#include // Constants constexpr uint32_t kCommissionPrepareTimeMs = 500; diff --git a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp index 53073160108036..cfe212fda00131 100644 --- a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp +++ b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.cpp @@ -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(context); - if (self->mDelegate) - { - self->mDelegate->OnCommissioningWindowOpened(remoteId, err, payload); - self->UnregisterDelegate(); - } - - LogErrorOnFailure(err); OnOpenBasicCommissioningWindowResponse(context, remoteId, err); } diff --git a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h index 7edcdba7115665..a8760a464827a9 100644 --- a/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h +++ b/examples/fabric-admin/commands/pairing/OpenCommissioningWindowCommand.h @@ -22,13 +22,6 @@ #include #include -class CommissioningWindowDelegate -{ -public: - virtual void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) = 0; - virtual ~CommissioningWindowDelegate() = default; -}; - class OpenCommissioningWindowCommand : public CHIPCommand { public: @@ -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; @@ -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; diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index ae8fa507ceaaa4..897b1b60e0b68b 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -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 @@ -115,19 +115,18 @@ void DeviceManager::RemoveSyncedDevice(NodeId nodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } -void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeout, uint32_t iterations, - uint32_t discriminator, const char * saltHex, const char * verifierHex) +void DeviceManager::OpenDeviceCommissioningWindow(NodeId nodeId, uint32_t commissioningTimeoutSec, uint32_t iterations, + 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 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, commissioningTimeoutSec, + iterations, discriminator, salt, verifier); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err)); + } } void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpointId) @@ -135,17 +134,20 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin // Open the commissioning window of a device from another fabric via its fabric bridge. // This method constructs and sends a command to open the commissioning window for a device // that is part of a different fabric, accessed through a fabric bridge. - StringBuilder commandBuilder; // Use random discriminator to have less chance of collision. 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, @@ -421,6 +423,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()); @@ -432,18 +435,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) diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 5f617845f7dc76..939329be82c691 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -94,18 +94,18 @@ class DeviceManager : public PairingDelegate * This function initiates the process to open the commissioning window for a device identified by the given node ID. * * @param nodeId The ID of the node that should open the commissioning window. - * @param commissioningTimeout The time in seconds before the commissioning window closes. This value determines + * @param commissioningTimeoutSec The time in seconds before the commissioning window closes. This value determines * how long the commissioning window remains open for incoming connections. * @param iterations The number of PBKDF (Password-Based Key Derivation Function) iterations to use * 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); + void OpenDeviceCommissioningWindow(chip::NodeId nodeId, uint32_t commissioningTimeoutSec, uint32_t iterations, + 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. diff --git a/examples/fabric-admin/device_manager/PairingManager.cpp b/examples/fabric-admin/device_manager/PairingManager.cpp new file mode 100644 index 00000000000000..aa56af4bc6bf4e --- /dev/null +++ b/examples/fabric-admin/device_manager/PairingManager.cpp @@ -0,0 +1,170 @@ +/* + * + * 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 +#include +#include + +using namespace ::chip; + +PairingManager::PairingManager() : + mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this), + mOnOpenCommissioningWindowVerifierCallback(OnOpenCommissioningWindowVerifierResponse, this) +{} + +void PairingManager::Init(Controller::DeviceCommissioner * commissioner) +{ + VerifyOrDie(mCommissioner == nullptr); + mCommissioner = commissioner; +} + +CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId endpointId, uint16_t commissioningTimeoutSec, + uint32_t iterations, uint16_t discriminator, const ByteSpan & salt, + const ByteSpan & verifier) +{ + if (mCommissioner == nullptr) + { + ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window"); + return CHIP_ERROR_INCORRECT_STATE; + } + + // Check if a window is already open + if (mWindowOpener != nullptr) + { + ChipLogError(NotSpecified, "A commissioning window is already open"); + return CHIP_ERROR_INCORRECT_STATE; + } + + auto params = Platform::MakeUnique(); + params->nodeId = nodeId; + params->endpointId = endpointId; + params->commissioningWindowTimeout = commissioningTimeoutSec; + params->iteration = iterations; + params->discriminator = discriminator; + + if (!salt.empty()) + { + if (salt.size() > sizeof(params->saltBuffer)) + { + ChipLogError(NotSpecified, "Salt size exceeds buffer capacity"); + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(params->saltBuffer, salt.data(), salt.size()); + params->salt = ByteSpan(params->saltBuffer, salt.size()); + } + + if (!verifier.empty()) + { + if (verifier.size() > sizeof(params->verifierBuffer)) + { + ChipLogError(NotSpecified, "Verifier size exceeds buffer capacity"); + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + memcpy(params->verifierBuffer, verifier.data(), verifier.size()); + params->verifier = ByteSpan(params->verifierBuffer, verifier.size()); + } + + // Schedule work on the Matter thread + return DeviceLayer::PlatformMgr().ScheduleWork(OnOpenCommissioningWindow, reinterpret_cast(params.release())); +} + +void PairingManager::OnOpenCommissioningWindow(intptr_t context) +{ + Platform::UniquePtr params(reinterpret_cast(context)); + PairingManager & self = PairingManager::Instance(); + + if (self.mCommissioner == nullptr) + { + ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window"); + return; + } + + self.mWindowOpener = Platform::MakeUnique(self.mCommissioner); + + if (!params->verifier.empty()) + { + if (params->salt.empty()) + { + ChipLogError(NotSpecified, "Salt is required when verifier is set"); + self.mWindowOpener.reset(); + return; + } + + CHIP_ERROR err = + self.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(NotSpecified, "Failed to open commissioning window with verifier: %s", ErrorStr(err)); + self.mWindowOpener.reset(); + } + } + else + { + SetupPayload ignored; + CHIP_ERROR err = self.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(NotSpecified, "Failed to open commissioning window with passcode: %s", ErrorStr(err)); + self.mWindowOpener.reset(); + } + } +} + +void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, SetupPayload payload) +{ + VerifyOrDie(context != nullptr); + PairingManager * self = static_cast(context); + if (self->mCommissioningWindowDelegate) + { + self->mCommissioningWindowDelegate->OnCommissioningWindowOpened(remoteId, err, payload); + self->SetOpenCommissioningWindowDelegate(nullptr); + } + + OnOpenCommissioningWindowVerifierResponse(context, remoteId, err); +} + +void PairingManager::OnOpenCommissioningWindowVerifierResponse(void * context, NodeId remoteId, CHIP_ERROR err) +{ + VerifyOrDie(context != nullptr); + PairingManager * self = static_cast(context); + LogErrorOnFailure(err); + + // Reset the window opener once the window operation is complete + self->mWindowOpener.reset(); +} diff --git a/examples/fabric-admin/device_manager/PairingManager.h b/examples/fabric-admin/device_manager/PairingManager.h new file mode 100644 index 00000000000000..de1c0887f3b1b7 --- /dev/null +++ b/examples/fabric-admin/device_manager/PairingManager.h @@ -0,0 +1,122 @@ +/* + * + * 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. + */ + +#pragma once + +#include +#include +#include + +class CommissioningWindowDelegate +{ +public: + virtual void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR err, chip::SetupPayload payload) = 0; + virtual ~CommissioningWindowDelegate() = default; +}; + +/** + * The PairingManager class is responsible for managing the commissioning and pairing process + * of Matter devices. PairingManager is designed to be used as a singleton, meaning that there + * should only be one instance of it running at any given time. + * + * Usage: + * + * 1. The class should be initialized when the system starts up, typically by invoking the static + * instance method to get the singleton. + * 2. To open a commissioning window, the appropriate method should be called on the PairingManager instance. + * 3. The PairingManager will handle the lifecycle of the CommissioningWindowOpener and ensure that + * resources are cleaned up appropriately when pairing is complete or the process is aborted. + * + * Example: + * + * @code + * PairingManager& manager = PairingManager::Instance(); + * manager.OpenCommissioningWindow(); + * @endcode + */ +class PairingManager +{ +public: + static PairingManager & Instance() + { + static PairingManager instance; + return instance; + } + + void Init(chip::Controller::DeviceCommissioner * commissioner); + + /** + * Opens a commissioning window on the specified node and endpoint. + * Only one commissioning window can be active at a time. If a commissioning + * window is already open, this function will return an error. + * + * @param nodeId The target node ID for commissioning. + * @param endpointId The target endpoint ID for commissioning. + * @param commissioningTimeoutSec Timeout for the commissioning window in seconds. + * @param iterations Iterations for PBKDF calculations. + * @param discriminator Discriminator for commissioning. + * @param salt Optional salt for verifier-based commissioning. + * @param verifier Optional verifier for enhanced commissioning security. + * + * @return CHIP_ERROR_INCORRECT_STATE if a commissioning window is already open. + */ + CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId, chip::EndpointId endpointId, uint16_t commissioningTimeoutSec, + uint32_t iterations, uint16_t discriminator, const chip::ByteSpan & salt, + const chip::ByteSpan & verifier); + + void SetOpenCommissioningWindowDelegate(CommissioningWindowDelegate * delegate) { mCommissioningWindowDelegate = delegate; } + +private: + PairingManager(); + PairingManager(const PairingManager &) = delete; + PairingManager & operator=(const PairingManager &) = delete; + + chip::Controller::DeviceCommissioner * mCommissioner = nullptr; + + /////////// Open Commissioning Window Command Interface ///////// + struct CommissioningWindowParams + { + chip::NodeId nodeId; + chip::EndpointId endpointId; + uint16_t commissioningWindowTimeout; + uint32_t iteration; + uint16_t discriminator; + chip::Optional setupPIN; + uint8_t verifierBuffer[chip::Crypto::kSpake2p_VerifierSerialized_Length]; + chip::ByteSpan verifier; + uint8_t saltBuffer[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length]; + chip::ByteSpan salt; + }; + + CommissioningWindowDelegate * mCommissioningWindowDelegate = nullptr; + + /** + * Holds the unique_ptr to the current CommissioningWindowOpener. + * Only one commissioning window opener can be active at a time. + * The pointer is reset when the commissioning window is closed or when an error occurs. + */ + chip::Platform::UniquePtr mWindowOpener; + + static void OnOpenCommissioningWindow(intptr_t context); + static void OnOpenCommissioningWindowResponse(void * context, chip::NodeId deviceId, CHIP_ERROR status, + chip::SetupPayload payload); + static void OnOpenCommissioningWindowVerifierResponse(void * context, chip::NodeId deviceId, CHIP_ERROR status); + + chip::Callback::Callback mOnOpenCommissioningWindowCallback; + chip::Callback::Callback mOnOpenCommissioningWindowVerifierCallback; +}; diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index 3fb181eac5f21b..6e5e2ec8d66442 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -86,21 +86,20 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate 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[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; - Encoding::BytesToHex(request.salt.bytes, request.salt.size, saltHex, sizeof(saltHex), Encoding::HexFlags::kNullTerminate); - - char verifierHex[Crypto::kSpake2p_VerifierSerialized_Length * 2 + 1]; - Encoding::BytesToHex(request.verifier.bytes, request.verifier.size, verifierHex, sizeof(verifierHex), - Encoding::HexFlags::kNullTerminate); - - ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId); - - DeviceMgr().OpenDeviceCommissioningWindow(nodeId, commissioningTimeout, iterations, discriminator, saltHex, verifierHex); + NodeId nodeId = request.node_id; + uint32_t commissioningTimeoutSec = request.commissioning_timeout; + uint32_t iterations = request.iterations; + uint16_t discriminator = request.discriminator; + + // Log the request details for debugging + ChipLogProgress(NotSpecified, + "Received OpenCommissioningWindow request: NodeId 0x%lx, Timeout: %u, Iterations: %u, Discriminator: %u", + static_cast(nodeId), commissioningTimeoutSec, iterations, discriminator); + + // Open the device commissioning window using raw binary data for salt and verifier + DeviceMgr().OpenDeviceCommissioningWindow(nodeId, commissioningTimeoutSec, iterations, discriminator, + ByteSpan(request.salt.bytes, request.salt.size), + ByteSpan(request.verifier.bytes, request.verifier.size)); response.success = true;