Skip to content

Commit

Permalink
[chip-tool] Add commands to generate/update onboarding payloads (#16704)
Browse files Browse the repository at this point in the history
* [Payload] Add SetAllowInvalidPayload and SetForceShortCode methods to QRCodeSetupPayloadGenerator and ManualSetupPayloadGenerator

* [chip-tool] Add a command to generate/update a qrcode and a command to generate/update a manual code
  • Loading branch information
vivien-apple authored Mar 30, 2022
1 parent 1c03d9c commit 6c692ab
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 7 deletions.
1 change: 1 addition & 0 deletions examples/chip-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ static_library("chip-tool-utils") {
"commands/pairing/OpenCommissioningWindowCommand.h",
"commands/pairing/PairingCommand.cpp",
"commands/payload/AdditionalDataParseCommand.cpp",
"commands/payload/SetupPayloadGenerateCommand.cpp",
"commands/payload/SetupPayloadParseCommand.cpp",
"commands/payload/SetupPayloadVerhoeff.cpp",
"commands/tests/TestCommand.cpp",
Expand Down
11 changes: 7 additions & 4 deletions examples/chip-tool/commands/payload/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@
#pragma once

#include "AdditionalDataParseCommand.h"
#include "SetupPayloadGenerateCommand.h"
#include "SetupPayloadParseCommand.h"
#include "SetupPayloadVerhoeff.h"

void registerCommandsPayload(Commands & commands)
{
const char * clusterName = "Payload";
commands_list clusterCommands = {
make_unique<SetupPayloadParseCommand>(),
make_unique<AdditionalDataParseCommand>(),
make_unique<SetupPayloadVerhoeffVerify>(),
make_unique<SetupPayloadVerhoeffGenerate>(),
make_unique<SetupPayloadGenerateQRCodeCommand>(), //
make_unique<SetupPayloadGenerateManualCodeCommand>(), //
make_unique<SetupPayloadParseCommand>(), //
make_unique<AdditionalDataParseCommand>(), //
make_unique<SetupPayloadVerhoeffVerify>(), //
make_unique<SetupPayloadVerhoeffGenerate>(), //
};

commands.Register(clusterName, clusterCommands);
Expand Down
107 changes: 107 additions & 0 deletions examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2022 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 "SetupPayloadGenerateCommand.h"
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>
#include <setup_payload/SetupPayload.h>

using namespace ::chip;

void SetupPayloadGenerateCommand::ConfigurePayload(SetupPayload & payload)
{
if (mDiscriminator.HasValue())
{
payload.discriminator = mDiscriminator.Value();
}

if (mSetUpPINCode.HasValue())
{
payload.setUpPINCode = mSetUpPINCode.Value();
}

if (mVersion.HasValue())
{
payload.version = mVersion.Value();
}

if (mVendorId.HasValue())
{
payload.vendorID = mVendorId.Value();
}

if (mProductId.HasValue())
{
payload.productID = mProductId.Value();
}

if (mCommissioningMode.HasValue())
{
payload.commissioningFlow = static_cast<CommissioningFlow>(mCommissioningMode.Value());
}
}

CHIP_ERROR SetupPayloadGenerateQRCodeCommand::Run()
{
SetupPayload payload;

if (mPayload.HasValue())
{
QRCodeSetupPayloadParser(mPayload.Value()).populatePayload(payload);
}

ConfigurePayload(payload);

if (mRendezvous.HasValue())
{
payload.rendezvousInformation.SetRaw(mRendezvous.Value());
}

QRCodeSetupPayloadGenerator generator(payload);
generator.SetAllowInvalidPayload(mAllowInvalidPayload.ValueOr(false));

std::string code;
ReturnErrorOnFailure(generator.payloadBase38Representation(code));
ChipLogProgress(chipTool, "QR Code: %s", code.c_str());

return CHIP_NO_ERROR;
}

CHIP_ERROR SetupPayloadGenerateManualCodeCommand::Run()
{
SetupPayload payload;

if (mPayload.HasValue())
{
ManualSetupPayloadParser(mPayload.Value()).populatePayload(payload);
}

ConfigurePayload(payload);

ManualSetupPayloadGenerator generator(payload);
generator.SetAllowInvalidPayload(mAllowInvalidPayload.ValueOr(false));
generator.SetForceShortCode(mForceShortCode.ValueOr(false));

std::string code;
ReturnErrorOnFailure(generator.payloadDecimalStringRepresentation(code));
ChipLogProgress(chipTool, "Manual Code: %s", code.c_str());

return CHIP_NO_ERROR;
}
76 changes: 76 additions & 0 deletions examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022 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 "../common/Command.h"
#include <setup_payload/SetupPayload.h>

class SetupPayloadGenerateCommand : public Command
{
public:
SetupPayloadGenerateCommand(const char * name) : Command(name)
{
AddArgument("payload", &mPayload);
AddArgument("discriminator", 0, UINT16_MAX, &mDiscriminator);
AddArgument("setup-pin-code", 0, UINT32_MAX, &mSetUpPINCode);
AddArgument("version", 0, UINT8_MAX, &mVersion);
AddArgument("vendor-id", 0, UINT16_MAX, &mVendorId);
AddArgument("product-id", 0, UINT16_MAX, &mProductId);
AddArgument("commissioning-mode", 0, UINT8_MAX, &mCommissioningMode);
AddArgument("allow-invalid-payload", 0, 1, &mAllowInvalidPayload);
}

protected:
void ConfigurePayload(chip::SetupPayload & payload);

chip::Optional<uint16_t> mDiscriminator;
chip::Optional<uint32_t> mSetUpPINCode;
chip::Optional<uint8_t> mVersion;
chip::Optional<uint16_t> mVendorId;
chip::Optional<uint16_t> mProductId;
chip::Optional<char *> mPayload;
chip::Optional<uint8_t> mCommissioningMode;
chip::Optional<bool> mAllowInvalidPayload;
};

class SetupPayloadGenerateQRCodeCommand : public SetupPayloadGenerateCommand
{
public:
SetupPayloadGenerateQRCodeCommand() : SetupPayloadGenerateCommand("generate-qrcode")
{
AddArgument("rendezvous", 0, UINT8_MAX, &mRendezvous);
}
CHIP_ERROR Run() override;

private:
chip::Optional<uint8_t> mRendezvous;
};

class SetupPayloadGenerateManualCodeCommand : public SetupPayloadGenerateCommand
{
public:
SetupPayloadGenerateManualCodeCommand() : SetupPayloadGenerateCommand("generate-manualcode")
{
AddArgument("force-short-code", 0, 1, &mForceShortCode);
}
CHIP_ERROR Run() override;

private:
chip::Optional<bool> mForceShortCode;
};
4 changes: 2 additions & 2 deletions src/setup_payload/ManualSetupPayloadGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ CHIP_ERROR ManualSetupPayloadGenerator::payloadDecimalStringRepresentation(Mutab
static_assert(kManualSetupChunk2PINCodeLsbitsLength + kManualSetupChunk3PINCodeMsbitsLength == kSetupPINCodeFieldLengthInBits,
"PIN code won't fit");

if (!mPayloadContents.isValidManualCode())
if (!mAllowInvalidPayload && !mPayloadContents.isValidManualCode())
{
ChipLogError(SetupPayload, "Failed encoding invalid payload");
return CHIP_ERROR_INVALID_ARGUMENT;
}

bool useLongCode = (mPayloadContents.commissioningFlow != CommissioningFlow::kStandard);
bool useLongCode = (mPayloadContents.commissioningFlow != CommissioningFlow::kStandard) && !mForceShortCode;

// Add two for the check digit and null terminator.
if ((useLongCode && outBuffer.size() < kManualSetupLongCodeCharLength + 2) ||
Expand Down
19 changes: 19 additions & 0 deletions src/setup_payload/ManualSetupPayloadGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,25 @@ class ManualSetupPayloadGenerator
// Populates decimal string representation of the payload into outDecimalString.
// Wrapper for using std::string.
CHIP_ERROR payloadDecimalStringRepresentation(std::string & outDecimalString);

/**
* This function disables internal checks about the validity of the generated payload.
* It allows using the generator to generate invalid payloads.
* Default is false.
*/
void SetAllowInvalidPayload(bool allow) { mAllowInvalidPayload = allow; }

/**
* This function allow forcing the generation of a short code when the commissioning
* flow is not standard by ignoring the vendor id and product id informations but with
* the VID/PID present flag set.
* Default is false.
*/
void SetForceShortCode(bool useShort) { mForceShortCode = useShort; }

private:
bool mAllowInvalidPayload = false;
bool mForceShortCode = false;
};

} // namespace chip
2 changes: 1 addition & 1 deletion src/setup_payload/QRCodeSetupPayloadGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ CHIP_ERROR QRCodeSetupPayloadGenerator::payloadBase38Representation(std::string
{
size_t tlvDataLengthInBytes = 0;

VerifyOrReturnError(mPayload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mAllowInvalidPayload || mPayload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(generateTLVFromOptionalData(mPayload, tlvDataStart, tlvDataStartSize, tlvDataLengthInBytes));

std::vector<uint8_t> bits(kTotalPayloadDataSizeInBytes + tlvDataLengthInBytes);
Expand Down
9 changes: 9 additions & 0 deletions src/setup_payload/QRCodeSetupPayloadGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,18 @@ class QRCodeSetupPayloadGenerator
*/
CHIP_ERROR payloadBase38Representation(std::string & base38Representation, uint8_t * tlvDataStart, uint32_t tlvDataStartSize);

/**
* This function disable internal checks about the validity of the generated payload.
* It allows using the generator to generates invalid payloads.
* Defaults is false.
*/
void SetAllowInvalidPayload(bool allow) { mAllowInvalidPayload = allow; }

private:
CHIP_ERROR generateTLVFromOptionalData(SetupPayload & outPayload, uint8_t * tlvDataStart, uint32_t maxLen,
size_t & tlvDataLengthInBytes);

bool mAllowInvalidPayload = false;
};

/**
Expand Down

0 comments on commit 6c692ab

Please sign in to comment.