From f31de53a37ddb8880d2b4752eff0b3d486738b63 Mon Sep 17 00:00:00 2001 From: chendejin Date: Sun, 18 Feb 2024 17:10:53 +0800 Subject: [PATCH] Setup controller by given fabric index, without providing NOC chain --- src/controller/CHIPDeviceController.cpp | 101 +++++++++++++++++- src/controller/CHIPDeviceController.h | 12 +++ .../CHIPDeviceControllerFactory.cpp | 4 + src/controller/CHIPDeviceControllerFactory.h | 7 ++ 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 57c75cd0d813ae..8aafe1ff5c1a06 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -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; @@ -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 originrcacBuf; + chip::Platform::ScopedMemoryBuffer rcacBuf; + chip::Platform::ScopedMemoryBuffer icacBuf; + chip::Platform::ScopedMemoryBuffer 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!"); + 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(); @@ -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; diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index a7e6f6dac4bcb9..e931b6909e897e 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -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; + chip::VendorId controllerVendorId; }; @@ -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 { diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp index ebc728ca206875..1909892801b2a4 100644 --- a/src/controller/CHIPDeviceControllerFactory.cpp +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -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) diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h index 6b4aa77fdc00c8..92487bababcc48 100644 --- a/src/controller/CHIPDeviceControllerFactory.h +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -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; + Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr; CommissioningDelegate * defaultCommissioner = nullptr; };