Skip to content

Commit

Permalink
Setup controller by given fabric index, without providing NOC chain
Browse files Browse the repository at this point in the history
  • Loading branch information
DejinChen committed Feb 26, 2024
1 parent acedec1 commit f5529c0
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 3 deletions.
101 changes: 98 additions & 3 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,25 @@ CHIP_ERROR DeviceController::Init(ControllerInitParams params)
mDNSResolver.SetCommissioningDelegate(this);
RegisterDeviceDiscoveryDelegate(params.deviceDiscoveryDelegate);

VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mOperationalCredentialsDelegate = params.operationalCredentialsDelegate;

mVendorId = params.controllerVendorId;
if (params.operationalKeypair != nullptr || !params.controllerNOC.empty() || !params.controllerRCAC.empty())
{
ReturnErrorOnFailure(InitControllerNOCChain(params));
}
else if (params.fabricIndex.HasValue())
{
VerifyOrReturnError(params.systemState->Fabrics()->FabricCount() > 0, CHIP_ERROR_INVALID_ARGUMENT);
if (params.systemState->Fabrics()->FindFabricWithIndex(params.fabricIndex.Value()) != nullptr)
{
// TODO: Check that there is no other controller with this mFabricIndex in this fabric table
mFabricIndex = params.fabricIndex.Value();
}
else
{
ChipLogError(Controller, "There is no fabric corresponding to the given fabricIndex");
return CHIP_ERROR_INVALID_ARGUMENT;
}
}

mSystemState = params.systemState->Retain();
mState = State::Initialized;
Expand Down Expand Up @@ -317,6 +328,88 @@ CHIP_ERROR DeviceController::InitControllerNOCChain(const ControllerInitParams &
return CHIP_NO_ERROR;
}

CHIP_ERROR DeviceController::UpdateControllerNOCChain(ControllerInitParams & params)
{
VerifyOrReturnError(mFabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INTERNAL);
auto * fabricTable = mSystemState->Fabrics();
VerifyOrReturnError(fabricTable->FindFabricWithIndex(mFabricIndex) != nullptr, CHIP_ERROR_INTERNAL);

constexpr uint32_t chipCertAllocatedLen = kMaxCHIPCertLength;
chip::Platform::ScopedMemoryBuffer<uint8_t> originrcacBuf;
chip::Platform::ScopedMemoryBuffer<uint8_t> rcacBuf;
chip::Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
chip::Platform::ScopedMemoryBuffer<uint8_t> nocBuf;

bool hasExternallyOwnedKeypair = false;
Crypto::P256Keypair * externalOperationalKeypair = nullptr;

if (params.operationalKeypair != nullptr)
{
hasExternallyOwnedKeypair = params.hasExternallyOwnedOperationalKeypair;
externalOperationalKeypair = params.operationalKeypair;
}

ReturnErrorCodeIf(!originrcacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
ReturnErrorCodeIf(!rcacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
ReturnErrorCodeIf(!icacBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);
ReturnErrorCodeIf(!nocBuf.Alloc(chipCertAllocatedLen), CHIP_ERROR_NO_MEMORY);

MutableByteSpan originrcacSpan(originrcacBuf.Get(), chipCertAllocatedLen);
ReturnErrorOnFailure(fabricTable->FetchRootCert(mFabricIndex, originrcacSpan));

MutableByteSpan rcacSpan(rcacBuf.Get(), chipCertAllocatedLen);
ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerRCAC, rcacSpan));

if (!originrcacSpan.data_equal(rcacSpan))
{
ChipLogError(Controller, "RCAC is not the same, update NOC chian failed!");
return CHIP_ERROR_INVALID_ARGUMENT;
}

MutableByteSpan icacSpan;
if (params.controllerICAC.empty())
{
ChipLogProgress(Controller, "Intermediate CA is not needed");
}
else
{
icacSpan = MutableByteSpan(icacBuf.Get(), chipCertAllocatedLen);
ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerICAC, icacSpan));
}

MutableByteSpan nocSpan = MutableByteSpan(nocBuf.Get(), chipCertAllocatedLen);
ReturnErrorOnFailure(ConvertX509CertToChipCert(params.controllerNOC, nocSpan));

CHIP_ERROR err = CHIP_NO_ERROR;

auto advertiseOperational =
params.enableServerInteractions ? FabricTable::AdvertiseIdentity::Yes : FabricTable::AdvertiseIdentity::No;

if (externalOperationalKeypair)
{
err = fabricTable->UpdatePendingFabricWithProvidedOpKey(mFabricIndex, nocSpan, icacSpan, externalOperationalKeypair,
hasExternallyOwnedKeypair, advertiseOperational);
}
else
{
VerifyOrReturnError(fabricTable->HasOperationalKeyForFabric(mFabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
err = fabricTable->UpdatePendingFabricWithOperationalKeystore(mFabricIndex, nocSpan, icacSpan, advertiseOperational);
}

if (err == CHIP_NO_ERROR)
{
err = fabricTable->CommitPendingFabricData();
}
else
{
fabricTable->RevertPendingFabricData();
}

ReturnErrorOnFailure(err);
return CHIP_NO_ERROR;
}

void DeviceController::Shutdown()
{
assertChipStackLockedByCurrentThread();
Expand Down Expand Up @@ -408,6 +501,8 @@ DeviceCommissioner::DeviceCommissioner() :

CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params)
{
VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mOperationalCredentialsDelegate = params.operationalCredentialsDelegate;
ReturnErrorOnFailure(DeviceController::Init(params));

mPairingDelegate = params.pairingDelegate;
Expand Down
12 changes: 12 additions & 0 deletions src/controller/CHIPDeviceController.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ struct ControllerInitParams
*/
bool removeFromFabricTableOnShutdown = true;

/**
* Specifies whether to utilize a fabric by a given FabricIndex for initialization.
* If enabled and neither the operational key pair nor the NOC chain are provided,
* then attempt to locate a fabric corresponding to the given FabricIndex.
*/
chip::Optional<FabricIndex> fabricIndex;

chip::VendorId controllerVendorId;
};

Expand Down Expand Up @@ -356,6 +363,11 @@ class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController
*/
CHIP_ERROR InitControllerNOCChain(const ControllerInitParams & params);

/**
* @brief Update the operational credentials after DeviceController Init.
*/
CHIP_ERROR UpdateControllerNOCChain(ControllerInitParams & params);

protected:
enum class State
{
Expand Down
4 changes: 4 additions & 0 deletions src/controller/CHIPDeviceControllerFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ void DeviceControllerFactory::PopulateInitParams(ControllerInitParams & controll
controllerParams.controllerVendorId = params.controllerVendorId;

controllerParams.enableServerInteractions = params.enableServerInteractions;
if (params.fabricIndex.HasValue())
{
controllerParams.fabricIndex.SetValue(params.fabricIndex.Value());
}
}

void DeviceControllerFactory::ControllerInitialized(const DeviceController & controller)
Expand Down
7 changes: 7 additions & 0 deletions src/controller/CHIPDeviceControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ struct SetupParams
*/
bool removeFromFabricTableOnShutdown = true;

/**
* Specifies whether to utilize a fabric by a given FabricIndex for initialization.
* If enabled and neither the operational key pair nor the NOC chain are provided,
* then attempt to locate a fabric corresponding to the given FabricIndex.
*/
chip::Optional<FabricIndex> fabricIndex;

Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr;
CommissioningDelegate * defaultCommissioner = nullptr;
};
Expand Down

0 comments on commit f5529c0

Please sign in to comment.