FS - Check VendorID and ProductID when commissioning. (#35187)
---------
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.cpp b/examples/fabric-admin/commands/pairing/PairingCommand.cpp
index 9a7adfa..55babdd 100644
--- a/examples/fabric-admin/commands/pairing/PairingCommand.cpp
+++ b/examples/fabric-admin/commands/pairing/PairingCommand.cpp
@@ -30,6 +30,7 @@
#include <protocols/secure_channel/PASESession.h>
#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>
+#include <setup_payload/SetupPayload.h>
#include <string>
@@ -40,6 +41,27 @@
using namespace ::chip;
using namespace ::chip::Controller;
+namespace {
+
+CHIP_ERROR GetPayload(const char * setUpCode, SetupPayload & payload)
+{
+ bool isQRCode = strncmp(setUpCode, kQRCodePrefix, strlen(kQRCodePrefix)) == 0;
+ if (isQRCode)
+ {
+ ReturnErrorOnFailure(QRCodeSetupPayloadParser(setUpCode).populatePayload(payload));
+ VerifyOrReturnError(payload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT);
+ }
+ else
+ {
+ ReturnErrorOnFailure(ManualSetupPayloadParser(setUpCode).populatePayload(payload));
+ VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+} // namespace
+
CHIP_ERROR PairingCommand::RunCommand()
{
CurrentCommissioner().RegisterPairingDelegate(this);
@@ -105,10 +127,7 @@
{
auto params = CommissioningParameters();
params.SetSkipCommissioningComplete(mSkipCommissioningComplete.ValueOr(false));
- if (mBypassAttestationVerifier.ValueOr(false))
- {
- params.SetDeviceAttestationDelegate(this);
- }
+ params.SetDeviceAttestationDelegate(this);
switch (mNetworkType)
{
@@ -564,18 +583,82 @@
chip::Optional<uint16_t> PairingCommand::FailSafeExpiryTimeoutSecs() const
{
- // We don't need to set additional failsafe timeout as we don't ask the final user if he wants to continue
+ // No manual input, so do not need to extend.
return chip::Optional<uint16_t>();
}
+bool PairingCommand::ShouldWaitAfterDeviceAttestation()
+{
+ // If there is a vendor ID and product ID, request OnDeviceAttestationCompleted().
+ // Currently this is added in the case that the example is performing reverse commissioning,
+ // but it would be an improvement to store that explicitly.
+ // TODO: Issue #35297 - [Fabric Sync] Improve where we get VID and PID when validating CCTRL CommissionNode command
+ SetupPayload payload;
+ CHIP_ERROR err = GetPayload(mOnboardingPayload, payload);
+ return err == CHIP_NO_ERROR && (payload.vendorID != 0 || payload.productID != 0);
+}
+
void PairingCommand::OnDeviceAttestationCompleted(chip::Controller::DeviceCommissioner * deviceCommissioner,
chip::DeviceProxy * device,
const chip::Credentials::DeviceAttestationVerifier::AttestationDeviceInfo & info,
chip::Credentials::AttestationVerificationResult attestationResult)
{
- // Bypass attestation verification, continue with success
- auto err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
- device, chip::Credentials::AttestationVerificationResult::kSuccess);
+ SetupPayload payload;
+ CHIP_ERROR parse_error = GetPayload(mOnboardingPayload, payload);
+ if (parse_error == CHIP_NO_ERROR && (payload.vendorID != 0 || payload.productID != 0))
+ {
+ if (payload.vendorID == 0 || payload.productID == 0)
+ {
+ ChipLogProgress(NotSpecified,
+ "Failed validation: vendorID or productID must not be 0."
+ "Requested VID: %u, Requested PID: %u.",
+ payload.vendorID, payload.productID);
+ deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
+ device, chip::Credentials::AttestationVerificationResult::kInvalidArgument);
+ return;
+ }
+
+ if (payload.vendorID != info.BasicInformationVendorId() || payload.productID != info.BasicInformationProductId())
+ {
+ ChipLogProgress(NotSpecified,
+ "Failed validation of vendorID or productID."
+ "Requested VID: %u, Requested PID: %u,"
+ "Detected VID: %u, Detected PID %u.",
+ payload.vendorID, payload.productID, info.BasicInformationVendorId(), info.BasicInformationProductId());
+ deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
+ device,
+ payload.vendorID == info.BasicInformationVendorId()
+ ? chip::Credentials::AttestationVerificationResult::kDacProductIdMismatch
+ : chip::Credentials::AttestationVerificationResult::kDacVendorIdMismatch);
+ return;
+ }
+
+ // NOTE: This will log errors even if the attestion was successful.
+ auto err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(device, attestationResult);
+ if (CHIP_NO_ERROR != err)
+ {
+ SetCommandExitStatus(err);
+ }
+ return;
+ }
+
+ // OnDeviceAttestationCompleted() is called if ShouldWaitAfterDeviceAttestation() returns true
+ // or if there is an attestation error. The conditions for ShouldWaitAfterDeviceAttestation() have
+ // already been checked, so the call to OnDeviceAttestationCompleted() was an error.
+ if (mBypassAttestationVerifier.ValueOr(false))
+ {
+ // Bypass attestation verification, continue with success
+ auto err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(
+ device, chip::Credentials::AttestationVerificationResult::kSuccess);
+ if (CHIP_NO_ERROR != err)
+ {
+ SetCommandExitStatus(err);
+ }
+ return;
+ }
+
+ // Don't bypass attestation, continue with error.
+ auto err = deviceCommissioner->ContinueCommissioningAfterDeviceAttestation(device, attestationResult);
if (CHIP_NO_ERROR != err)
{
SetCommandExitStatus(err);
diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.h b/examples/fabric-admin/commands/pairing/PairingCommand.h
index 647f2c3..293c369 100644
--- a/examples/fabric-admin/commands/pairing/PairingCommand.h
+++ b/examples/fabric-admin/commands/pairing/PairingCommand.h
@@ -221,6 +221,7 @@
/////////// DeviceAttestationDelegate Interface /////////
chip::Optional<uint16_t> FailSafeExpiryTimeoutSecs() const override;
+ bool ShouldWaitAfterDeviceAttestation() override;
void OnDeviceAttestationCompleted(chip::Controller::DeviceCommissioner * deviceCommissioner, chip::DeviceProxy * device,
const chip::Credentials::DeviceAttestationVerifier::AttestationDeviceInfo & info,
chip::Credentials::AttestationVerificationResult attestationResult) override;