Skip to content

Commit

Permalink
Spin up commissioners in chip-tool as needed. (project-chip#21830)
Browse files Browse the repository at this point in the history
The basic change is that instead of spinning up commissioners during "stack
startup" for the three default identities plus the command's identity (in case
that's not one of the three defaults) we:

1) Spin up the commissioner for the command's identity when we're actually
   running the command (on the Matter event loop).  This allows commands in
   interactive mode to use an identity that is not one of the three default
   identities and fixes project-chip#21828

2) Spin up commissioners as needed when they are requested.  This allows YAML
   test steps (which are not distinct commands) to use an identity that is not
   one of the three default identities.
  • Loading branch information
bzbarsky-apple authored and isiu-apple committed Sep 16, 2022
1 parent 50edaa8 commit 2c87502
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 55 deletions.
130 changes: 79 additions & 51 deletions examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ constexpr chip::FabricId kIdentityGammaFabricId = 3;
constexpr chip::FabricId kIdentityOtherFabricId = 4;
constexpr const char * kTrustStorePathVariable = "CHIPTOOL_PAA_TRUST_STORE_PATH";

const chip::Credentials::AttestationTrustStore * CHIPCommand::sPaaTrustStore = nullptr;
chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric };

namespace {
const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStore(const char * paaTrustStorePath)
{
Expand Down Expand Up @@ -86,10 +89,10 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
// and the DeviceControllerFactory all "share" in the same underlying data.
// Different commissioner implementations may want to use alternate implementations
// of GroupDataProvider for injection through factoryInitParams.
mGroupDataProvider.SetStorageDelegate(&mDefaultStorage);
ReturnLogErrorOnFailure(mGroupDataProvider.Init());
chip::Credentials::SetGroupDataProvider(&mGroupDataProvider);
factoryInitParams.groupDataProvider = &mGroupDataProvider;
sGroupDataProvider.SetStorageDelegate(&mDefaultStorage);
ReturnLogErrorOnFailure(sGroupDataProvider.Init());
chip::Credentials::SetGroupDataProvider(&sGroupDataProvider);
factoryInitParams.groupDataProvider = &sGroupDataProvider;

uint16_t port = mDefaultStorage.GetListenPort();
if (port != 0)
Expand All @@ -108,11 +111,10 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
mPaaTrustStorePath.SetValue(trust_store_path);
}
}
const chip::Credentials::AttestationTrustStore * trustStore = mPaaTrustStorePath.HasValue()
? GetTestFileAttestationTrustStore(mPaaTrustStorePath.Value())
: chip::Credentials::GetTestAttestationTrustStore();
sPaaTrustStore = mPaaTrustStorePath.HasValue() ? GetTestFileAttestationTrustStore(mPaaTrustStorePath.Value())
: chip::Credentials::GetTestAttestationTrustStore();
;
if (mPaaTrustStorePath.HasValue() && trustStore == nullptr)
if (mPaaTrustStorePath.HasValue() && sPaaTrustStore == nullptr)
{
ChipLogError(chipTool, "No PAAs found in path: %s", mPaaTrustStorePath.Value());
ChipLogError(chipTool,
Expand All @@ -123,42 +125,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
return CHIP_ERROR_INVALID_ARGUMENT;
}

ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId, trustStore));
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityAlpha, kIdentityAlphaFabricId, trustStore));
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityBeta, kIdentityBetaFabricId, trustStore));
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityGamma, kIdentityGammaFabricId, trustStore));

std::string name = GetIdentity();
chip::FabricId fabricId = strtoull(name.c_str(), nullptr, 0);
if (fabricId >= kIdentityOtherFabricId)
{
ReturnLogErrorOnFailure(InitializeCommissioner(name, fabricId, trustStore));
}

// Initialize Group Data, including IPK
for (auto it = mCommissioners.begin(); it != mCommissioners.end(); it++)
{
if (0 == it->first.compare(kIdentityNull))
{
continue;
}
const chip::Controller::DeviceCommissioner * controller = it->second.get();

chip::FabricIndex fabricIndex = controller->GetFabricIndex();
uint8_t compressed_fabric_id[sizeof(uint64_t)];
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
ReturnLogErrorOnFailure(controller->GetCompressedFabricIdBytes(compressed_fabric_id_span));

ReturnLogErrorOnFailure(chip::GroupTesting::InitData(&mGroupDataProvider, fabricIndex, compressed_fabric_id_span));

// Configure the default IPK for all fabrics used by CHIP-tool. The epoch
// key is the same, but the derived keys will be different for each fabric.
// This has to be done here after we know the Compressed Fabric ID of all
// chip-tool-managed fabrics
chip::ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
ReturnLogErrorOnFailure(
chip::Credentials::SetSingleIpkEpochKey(&mGroupDataProvider, fabricIndex, defaultIpk, compressed_fabric_id_span));
}
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityNull, kIdentityNullFabricId));

return CHIP_NO_ERROR;
}
Expand All @@ -183,6 +150,40 @@ void CHIPCommand::MaybeTearDownStack()
StopTracing();
}

CHIP_ERROR CHIPCommand::EnsureCommissionerForIdentity(std::string identity)
{
if (mCommissioners.find(identity) != mCommissioners.end())
{
return CHIP_NO_ERROR;
}

// Need to initialize the commissioner.
chip::FabricId fabricId;
if (identity == kIdentityAlpha)
{
fabricId = kIdentityAlphaFabricId;
}
else if (identity == kIdentityBeta)
{
fabricId = kIdentityBetaFabricId;
}
else if (identity == kIdentityGamma)
{
fabricId = kIdentityGammaFabricId;
}
else
{
fabricId = strtoull(identity.c_str(), nullptr, 0);
if (fabricId < kIdentityOtherFabricId)
{
ChipLogError(chipTool, "Invalid identity: %s", identity.c_str());
return CHIP_ERROR_INVALID_ARGUMENT;
}
}

return InitializeCommissioner(identity, fabricId);
}

CHIP_ERROR CHIPCommand::Run()
{
ReturnErrorOnFailure(MaybeSetUpStack());
Expand Down Expand Up @@ -313,13 +314,18 @@ chip::FabricId CHIPCommand::CurrentCommissionerId()

chip::Controller::DeviceCommissioner & CHIPCommand::CurrentCommissioner()
{
auto item = mCommissioners.find(GetIdentity());
return *item->second;
return GetCommissioner(GetIdentity());
}

chip::Controller::DeviceCommissioner & CHIPCommand::GetCommissioner(const char * identity)
chip::Controller::DeviceCommissioner & CHIPCommand::GetCommissioner(std::string identity)
{
// We don't have a great way to handle commissioner setup failures here.
// This only matters for commands (like TestCommand) that involve multiple
// identities.
VerifyOrDie(EnsureCommissionerForIdentity(identity) == CHIP_NO_ERROR);

auto item = mCommissioners.find(identity);
VerifyOrDie(item != mCommissioners.end());
return *item->second;
}

Expand All @@ -328,8 +334,7 @@ void CHIPCommand::ShutdownCommissioner(std::string key)
mCommissioners[key].get()->Shutdown();
}

CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId fabricId,
const chip::Credentials::AttestationTrustStore * trustStore)
CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId fabricId)
{
chip::Platform::ScopedMemoryBuffer<uint8_t> noc;
chip::Platform::ScopedMemoryBuffer<uint8_t> icac;
Expand All @@ -338,7 +343,7 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f
std::unique_ptr<ChipDeviceCommissioner> commissioner = std::make_unique<ChipDeviceCommissioner>();
chip::Controller::SetupParams commissionerParams;

ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, trustStore));
ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sPaaTrustStore));

VerifyOrReturnError(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
VerifyOrReturnError(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
Expand Down Expand Up @@ -375,6 +380,24 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f
commissionerParams.controllerVendorId = chip::VendorId::TestVendor1;

ReturnLogErrorOnFailure(DeviceControllerFactory::GetInstance().SetupCommissioner(commissionerParams, *(commissioner.get())));

if (key != kIdentityNull)
{
// Initialize Group Data, including IPK
chip::FabricIndex fabricIndex = commissioner->GetFabricIndex();
uint8_t compressed_fabric_id[sizeof(uint64_t)];
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
ReturnLogErrorOnFailure(commissioner->GetCompressedFabricIdBytes(compressed_fabric_id_span));

ReturnLogErrorOnFailure(chip::GroupTesting::InitData(&sGroupDataProvider, fabricIndex, compressed_fabric_id_span));

// Configure the default IPK for all fabrics used by CHIP-tool. The epoch
// key is the same, but the derived keys will be different for each fabric.
chip::ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
ReturnLogErrorOnFailure(
chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, fabricIndex, defaultIpk, compressed_fabric_id_span));
}

mCommissioners[key] = std::move(commissioner);

return CHIP_NO_ERROR;
Expand All @@ -383,7 +406,12 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f
void CHIPCommand::RunQueuedCommand(intptr_t commandArg)
{
auto * command = reinterpret_cast<CHIPCommand *>(commandArg);
CHIP_ERROR err = command->RunCommand();
CHIP_ERROR err = command->EnsureCommissionerForIdentity(command->GetIdentity());
if (err == CHIP_NO_ERROR)
{
err = command->RunCommand();
}

if (err != CHIP_NO_ERROR)
{
command->SetCommandExitStatus(err);
Expand Down
13 changes: 9 additions & 4 deletions examples/chip-tool/commands/common/CHIPCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class CHIPCommand : public Command
chip::PersistentStorageOperationalKeystore mOperationalKeystore;
chip::Credentials::PersistentStorageOpCertStore mOpCertStore;

chip::Credentials::GroupDataProviderImpl mGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric };
static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
CredentialIssuerCommands * mCredIssuerCmds;

std::string GetIdentity();
Expand All @@ -135,14 +135,15 @@ class CHIPCommand : public Command
// --identity "instance name" when running a command.
ChipDeviceCommissioner & CurrentCommissioner();

ChipDeviceCommissioner & GetCommissioner(const char * identity);
ChipDeviceCommissioner & GetCommissioner(std::string identity);

private:
CHIP_ERROR MaybeSetUpStack();
void MaybeTearDownStack();

CHIP_ERROR InitializeCommissioner(std::string key, chip::FabricId fabricId,
const chip::Credentials::AttestationTrustStore * trustStore);
CHIP_ERROR EnsureCommissionerForIdentity(std::string identity);

CHIP_ERROR InitializeCommissioner(std::string key, chip::FabricId fabricId);
void ShutdownCommissioner(std::string key);
chip::FabricId CurrentCommissionerId();
static std::map<std::string, std::unique_ptr<ChipDeviceCommissioner>> mCommissioners;
Expand All @@ -153,6 +154,10 @@ class CHIPCommand : public Command
chip::Optional<uint16_t> mBleAdapterId;
chip::Optional<char *> mPaaTrustStorePath;

// Cached trust store so commands other than the original startup command
// can spin up commissioners as needed.
static const chip::Credentials::AttestationTrustStore * sPaaTrustStore;

static void RunQueuedCommand(intptr_t commandArg);

CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL;
Expand Down

0 comments on commit 2c87502

Please sign in to comment.