From 125972018a8dff426f97744650966c84512a73f3 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Tue, 5 Oct 2021 11:36:25 -0700 Subject: [PATCH] Enable Fabric Scoped Storage --- .../chip-tool/config/PersistentStorage.cpp | 37 ++++-- examples/chip-tool/config/PersistentStorage.h | 7 +- .../linux/PersistentStorage.cpp | 33 ++++-- .../linux/PersistentStorage.h | 7 +- examples/platform/linux/AppMain.cpp | 6 +- src/app/server/Server.h | 7 +- src/controller/CHIPDevice.cpp | 15 ++- src/controller/CHIPDevice.h | 20 +++- src/controller/CHIPDeviceController.cpp | 28 ++--- src/controller/CHIPDeviceControllerFactory.h | 2 +- .../ExampleOperationalCredentialsIssuer.cpp | 20 ++-- .../java/AndroidDeviceControllerWrapper.cpp | 17 +-- .../java/AndroidDeviceControllerWrapper.h | 7 +- .../ChipDeviceController-StorageDelegate.cpp | 8 +- .../ChipDeviceController-StorageDelegate.h | 7 +- .../python/chip/internal/CommissionerImpl.cpp | 7 +- .../Framework Helpers/DefaultsUtils.h | 4 - .../Framework Helpers/DefaultsUtils.m | 27 +---- .../TemperatureSensorViewController.m | 18 +-- .../Framework/CHIP/CHIPDeviceController.h | 2 + .../Framework/CHIP/CHIPDeviceController.mm | 20 +++- .../CHIP/CHIPOperationalCredentialsDelegate.h | 2 + .../CHIPOperationalCredentialsDelegate.mm | 9 +- .../CHIP/CHIPPersistentStorageDelegate.h | 13 +- .../CHIPPersistentStorageDelegateBridge.h | 7 +- .../CHIPPersistentStorageDelegateBridge.mm | 39 ++++-- .../CHIP/templates/clusters-tests.zapt | 2 +- .../Framework/CHIPTests/CHIPClustersTests.m | 2 +- .../Framework/CHIPTests/CHIPControllerTests.m | 8 +- src/lib/core/CHIPError.h | 10 ++ src/lib/core/CHIPPersistentStorageDelegate.h | 20 +++- .../secure_channel/tests/TestCASESession.cpp | 7 +- src/transport/FabricTable.cpp | 111 +++++++++++++++++- src/transport/FabricTable.h | 12 +- 34 files changed, 366 insertions(+), 175 deletions(-) diff --git a/examples/chip-tool/config/PersistentStorage.cpp b/examples/chip-tool/config/PersistentStorage.cpp index 75396aa5a1adab..5ed8fe4cf010a1 100644 --- a/examples/chip-tool/config/PersistentStorage.cpp +++ b/examples/chip-tool/config/PersistentStorage.cpp @@ -91,11 +91,23 @@ CHIP_ERROR PersistentStorage::Init() return err; } -CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, uint16_t & size) +String GetSectionName(const CompressedFabricId fabricId) +{ + if (fabricId == kUndefinedCompressedFabricId) + { + return kDefaultSectionName; + } + else + { + return std::to_string(fabricId); + } +} + +CHIP_ERROR PersistentStorage::SyncGetKeyValue(const CompressedFabricId fabricId, const char * key, void * value, uint16_t & size) { std::string iniValue; - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; auto it = section.find(key); ReturnErrorCodeIf(it == section.end(), CHIP_ERROR_KEY_NOT_FOUND); @@ -116,21 +128,22 @@ CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, ui return CHIP_NO_ERROR; } -CHIP_ERROR PersistentStorage::SyncSetKeyValue(const char * key, const void * value, uint16_t size) +CHIP_ERROR PersistentStorage::SyncSetKeyValue(const CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) { - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; section[key] = StringToBase64(std::string(static_cast(value), size)); - mConfig.sections[kDefaultSectionName] = section; + mConfig.sections[GetSectionName(fabricId)] = section; return CommitConfig(); } -CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const char * key) +CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const CompressedFabricId fabricId, const char * key) { - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; section.erase(key); - mConfig.sections[kDefaultSectionName] = section; + mConfig.sections[GetSectionName(fabricId)] = section; return CommitConfig(); } @@ -163,7 +176,7 @@ uint16_t PersistentStorage::GetListenPort() char value[6]; uint16_t size = static_cast(sizeof(value)); - err = SyncGetKeyValue(kPortKey, value, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, kPortKey, value, size); if (CHIP_NO_ERROR == err) { uint16_t tmpValue; @@ -185,7 +198,7 @@ LogCategory PersistentStorage::GetLoggingLevel() char value[9]; uint16_t size = static_cast(sizeof(value)); - err = SyncGetKeyValue(kLoggingKey, value, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, kLoggingKey, value, size); if (CHIP_NO_ERROR == err) { if (strcasecmp(value, "none") == 0) @@ -215,7 +228,7 @@ NodeId PersistentStorage::GetNodeId(const char * key, NodeId defaultVal) uint64_t nodeId; uint16_t size = static_cast(sizeof(nodeId)); - err = SyncGetKeyValue(key, &nodeId, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, key, &nodeId, size); if (err == CHIP_NO_ERROR) { return static_cast(Encoding::LittleEndian::HostSwap64(nodeId)); @@ -237,7 +250,7 @@ NodeId PersistentStorage::GetRemoteNodeId() CHIP_ERROR PersistentStorage::SetNodeId(const char * key, NodeId value) { uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value); - return SyncSetKeyValue(key, &nodeId, sizeof(nodeId)); + return SyncSetKeyValue(kUndefinedCompressedFabricId, key, &nodeId, sizeof(nodeId)); } CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId nodeId) diff --git a/examples/chip-tool/config/PersistentStorage.h b/examples/chip-tool/config/PersistentStorage.h index cdd31661c90536..1f7c4a89164149 100644 --- a/examples/chip-tool/config/PersistentStorage.h +++ b/examples/chip-tool/config/PersistentStorage.h @@ -29,9 +29,10 @@ class PersistentStorage : public chip::PersistentStorageDelegate CHIP_ERROR Init(); /////////// PersistentStorageDelegate Interface ///////// - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; - CHIP_ERROR SyncDeleteKeyValue(const char * key) override; + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override; + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override; + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override; uint16_t GetListenPort(); chip::Logging::LogCategory GetLoggingLevel(); diff --git a/examples/ota-requestor-app/linux/PersistentStorage.cpp b/examples/ota-requestor-app/linux/PersistentStorage.cpp index 3f4a7a5b1a63e9..32e009e8d0c428 100644 --- a/examples/ota-requestor-app/linux/PersistentStorage.cpp +++ b/examples/ota-requestor-app/linux/PersistentStorage.cpp @@ -91,11 +91,23 @@ CHIP_ERROR PersistentStorage::Init() return err; } -CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, uint16_t & size) +String GetSectionName(const CompressedFabricId fabricId) +{ + if (fabricId == kUndefinedCompressedFabricId) + { + return kDefaultSectionName; + } + else + { + return std::to_string(fabricId); + } +} + +CHIP_ERROR PersistentStorage::SyncGetKeyValue(const CompressedFabricId fabricId, const char * key, void * value, uint16_t & size) { std::string iniValue; - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; auto it = section.find(key); ReturnErrorCodeIf(it == section.end(), CHIP_ERROR_KEY_NOT_FOUND); @@ -116,18 +128,19 @@ CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, ui return CHIP_NO_ERROR; } -CHIP_ERROR PersistentStorage::SyncSetKeyValue(const char * key, const void * value, uint16_t size) +CHIP_ERROR PersistentStorage::SyncSetKeyValue(const CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) { - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; section[key] = StringToBase64(std::string(static_cast(value), size)); mConfig.sections[kDefaultSectionName] = section; return CommitConfig(); } -CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const char * key) +CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const CompressedFabricId fabricId, const char * key) { - auto section = mConfig.sections[kDefaultSectionName]; + auto section = mConfig.sections[GetSectionName(fabricId)]; section.erase(key); mConfig.sections[kDefaultSectionName] = section; @@ -163,7 +176,7 @@ uint16_t PersistentStorage::GetListenPort() char value[6]; uint16_t size = static_cast(sizeof(value)); - err = SyncGetKeyValue(kPortKey, value, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, kPortKey, value, size); if (CHIP_NO_ERROR == err) { uint16_t tmpValue; @@ -185,7 +198,7 @@ LogCategory PersistentStorage::GetLoggingLevel() char value[9]; uint16_t size = static_cast(sizeof(value)); - err = SyncGetKeyValue(kLoggingKey, value, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, kLoggingKey, value, size); if (CHIP_NO_ERROR == err) { if (strcasecmp(value, "none") == 0) @@ -215,7 +228,7 @@ NodeId PersistentStorage::GetNodeId(const char * key, NodeId defaultVal) uint64_t nodeId; uint16_t size = static_cast(sizeof(nodeId)); - err = SyncGetKeyValue(key, &nodeId, size); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, key, &nodeId, size); if (err == CHIP_NO_ERROR) { return static_cast(Encoding::LittleEndian::HostSwap64(nodeId)); @@ -237,7 +250,7 @@ NodeId PersistentStorage::GetRemoteNodeId() CHIP_ERROR PersistentStorage::SetNodeId(const char * key, NodeId value) { uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value); - return SyncSetKeyValue(key, &nodeId, sizeof(nodeId)); + return SyncSetKeyValue(kUndefinedCompressedFabricId, key, &nodeId, sizeof(nodeId)); } CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId nodeId) diff --git a/examples/ota-requestor-app/linux/PersistentStorage.h b/examples/ota-requestor-app/linux/PersistentStorage.h index 35cc775f81b8d5..30a4852a451c01 100644 --- a/examples/ota-requestor-app/linux/PersistentStorage.h +++ b/examples/ota-requestor-app/linux/PersistentStorage.h @@ -29,9 +29,10 @@ class PersistentStorage : public chip::PersistentStorageDelegate CHIP_ERROR Init(); /////////// PersistentStorageDelegate Interface ///////// - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; - CHIP_ERROR SyncDeleteKeyValue(const char * key) override; + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override; + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override; + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override; uint16_t GetListenPort(); chip::Logging::LogCategory GetLoggingLevel(); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 87c7182ed71305..5ba6eaf54cc458 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -185,19 +185,19 @@ using namespace ::chip::Controller; class MyServerStorageDelegate : public PersistentStorageDelegate { - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override + CHIP_ERROR SyncGetKeyValue(const CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override { ChipLogProgress(AppServer, "Retrieved value from server storage."); return PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size); } - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override + CHIP_ERROR SyncSetKeyValue(const CompressedFabricId fabricId, const char * key, const void * value, uint16_t size) override { ChipLogProgress(AppServer, "Stored value in server storage"); return PersistedStorage::KeyValueStoreMgr().Put(key, value, size); } - CHIP_ERROR SyncDeleteKeyValue(const char * key) override + CHIP_ERROR SyncDeleteKeyValue(const CompressedFabricId fabricId, const char * key) override { ChipLogProgress(AppServer, "Delete value in server storage"); return PersistedStorage::KeyValueStoreMgr().Delete(key); diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 968e6dbcf4176c..8e5da6bb2fbf09 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -86,23 +86,24 @@ class Server : public Messaging::ExchangeDelegate static Server sServer; + // TODO Server implementations do not separate storage based on fabric class ServerStorageDelegate : public PersistentStorageDelegate { - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override + CHIP_ERROR SyncGetKeyValue(const CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override { ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size)); ChipLogProgress(AppServer, "Retrieved from server storage: %s", key); return CHIP_NO_ERROR; } - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override + CHIP_ERROR SyncSetKeyValue(const CompressedFabricId fabricId, const char * key, const void * value, uint16_t size) override { ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size)); ChipLogProgress(AppServer, "Saved into server storage: %s", key); return CHIP_NO_ERROR; } - CHIP_ERROR SyncDeleteKeyValue(const char * key) override + CHIP_ERROR SyncDeleteKeyValue(const CompressedFabricId fabricId, const char * key) override { ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key)); ChipLogProgress(AppServer, "Deleted from server storage: %s", key); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 1e8ee48f042301..80d16166c4f982 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -114,10 +114,11 @@ CHIP_ERROR Device::Serialize(SerializedDevice & output) CHIP_ZERO_AT(serializable); CHIP_ZERO_AT(output); - serializable.mOpsCreds = mPairing; - serializable.mDeviceId = Encoding::LittleEndian::HostSwap64(mDeviceId); - serializable.mDevicePort = Encoding::LittleEndian::HostSwap16(mDeviceAddress.GetPort()); - serializable.mFabricIndex = Encoding::LittleEndian::HostSwap16(mFabricIndex); + serializable.mOpsCreds = mPairing; + serializable.mDeviceId = Encoding::LittleEndian::HostSwap64(mDeviceId); + serializable.mDevicePort = Encoding::LittleEndian::HostSwap16(mDeviceAddress.GetPort()); + serializable.mFabricIndex = Encoding::LittleEndian::HostSwap16(mFabricIndex); + serializable.mCompressedFabricId = Encoding::LittleEndian::HostSwap64(mCompressedFabricId); // The connection state could be null if the device is moving from PASE connection to CASE connection. // The device parameters (e.g. mDeviceOperationalCertProvisioned) are updated during this transition. @@ -186,6 +187,7 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) const uint16_t index = Encoding::LittleEndian::HostSwap16(serializable.mFabricIndex); mLocalMessageCounter = Encoding::LittleEndian::HostSwap32(serializable.mLocalMessageCounter); mPeerMessageCounter = Encoding::LittleEndian::HostSwap32(serializable.mPeerMessageCounter); + mCompressedFabricId = Encoding::LittleEndian::HostSwap64(serializable.mCompressedFabricId); VerifyOrReturnError(CanCastTo(index), CHIP_ERROR_INVALID_ARGUMENT); mFabricIndex = static_cast(index); @@ -243,8 +245,9 @@ CHIP_ERROR Device::Persist() ReturnErrorOnFailure(Serialize(serialized)); // TODO: no need to base-64 the serialized values AGAIN - PERSISTENT_KEY_OP(GetDeviceId(), kPairedDeviceKeyPrefix, key, - error = mStorageDelegate->SyncSetKeyValue(key, serialized.inner, sizeof(serialized.inner))); + PERSISTENT_KEY_OP( + GetDeviceId(), kPairedDeviceKeyPrefix, key, + error = mStorageDelegate->SyncSetKeyValue(mCompressedFabricId, key, serialized.inner, sizeof(serialized.inner))); if (error != CHIP_NO_ERROR) { ChipLogError(Controller, "Failed to persist device %" CHIP_ERROR_FORMAT, error.Format()); diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 91a20aa27e339d..5c22991a97ecb7 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -171,7 +171,7 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta * still using them, it can lead to unknown behavior and crashes. * * @param[in] params Wrapper object for transport manager etc. - * @param[in] fabric Local administrator that's initializing this device object + * @param[in] fabric Local administrator that's initializing this device object */ void Init(ControllerDeviceInitParams params, FabricIndex fabric) { @@ -186,6 +186,14 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta #if CONFIG_NETWORK_LAYER_BLE mBleLayer = params.bleLayer; #endif + if (mFabricsTable != nullptr && mFabricIndex != kUndefinedFabricIndex) + { + FabricInfo * fabricInfo = mFabricsTable->FindFabricWithIndex(mFabricIndex); + if (fabricInfo != nullptr) + { + mCompressedFabricId = fabricInfo->GetCompressedFabricId(); + } + } } /** @@ -202,7 +210,7 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta * @param[in] params Wrapper object for transport manager etc. * @param[in] deviceId Node ID of the device * @param[in] peerAddress The location of the peer. MUST be of type Transport::Type::kUdp - * @param[in] fabric Local administrator that's initializing this device object + * @param[in] fabric Local administrator that's initializing this device object */ void Init(ControllerDeviceInitParams params, NodeId deviceId, const Transport::PeerAddress & peerAddress, FabricIndex fabric) { @@ -526,7 +534,8 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta static void OnOpenPairingWindowSuccessResponse(void * context); static void OnOpenPairingWindowFailureResponse(void * context, uint8_t status); - FabricIndex mFabricIndex = kUndefinedFabricIndex; + CompressedFabricId mCompressedFabricId = kUndefinedCompressedFabricId; + FabricIndex mFabricIndex = kUndefinedFabricIndex; FabricTable * mFabricsTable = nullptr; @@ -607,8 +616,9 @@ typedef struct SerializableDevice PASESessionSerializable mOpsCreds; uint64_t mDeviceId; /* This field is serialized in LittleEndian byte order */ uint8_t mDeviceAddr[INET6_ADDRSTRLEN]; - uint16_t mDevicePort; /* This field is serialized in LittleEndian byte order */ - uint16_t mFabricIndex; /* This field is serialized in LittleEndian byte order */ + uint16_t mDevicePort; /* This field is serialized in LittleEndian byte order */ + uint16_t mFabricIndex; /* This field is serialized in LittleEndian byte order */ + uint64_t mCompressedFabricId; /* This field is serialized in LittleEndian byte order */ uint8_t mDeviceTransport; uint8_t mDeviceOperationalCertProvisioned; uint8_t mInterfaceName[kMaxInterfaceName]; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index cbb3243a46fa3c..b6ac60504747ea 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -188,14 +188,12 @@ CHIP_ERROR DeviceController::ProcessControllerNOCChain(const ControllerInitParam ReturnErrorOnFailure(newFabric.SetNOCCert(chipCertSpan)); newFabric.SetVendorId(params.controllerVendorId); - FabricInfo * fabric = params.systemState->Fabrics()->FindFabricWithIndex(mFabricIndex); - ReturnErrorCodeIf(fabric == nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(params.systemState->Fabrics()->AddNewFabric(newFabric, &mFabricIndex)); - ReturnErrorOnFailure(fabric->SetFabricInfo(newFabric)); - mLocalId = fabric->GetPeerId(); - mVendorId = fabric->GetVendorId(); + mLocalId = newFabric.GetPeerId(); + mVendorId = newFabric.GetVendorId(); - mFabricId = fabric->GetFabricId(); + mFabricId = newFabric.GetFabricId(); ChipLogProgress(Controller, "Joined the fabric at index %d. Compressed fabric ID is: 0x" ChipLogFormatX64, mFabricIndex, ChipLogValueX64(GetCompressedFabricId())); @@ -266,7 +264,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) uint16_t size = sizeof(deviceInfo.inner); PERSISTENT_KEY_OP(deviceId, kPairedDeviceKeyPrefix, key, - err = mStorageDelegate->SyncGetKeyValue(key, deviceInfo.inner, size)); + err = mStorageDelegate->SyncGetKeyValue(GetCompressedFabricId(), key, deviceInfo.inner, size)); SuccessOrExit(err); VerifyOrExit(size <= sizeof(deviceInfo.inner), err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); @@ -481,7 +479,7 @@ CHIP_ERROR DeviceController::InitializePairedDeviceList() CHIP_ERROR lookupError = CHIP_NO_ERROR; PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, - lookupError = mStorageDelegate->SyncGetKeyValue(key, buffer, size)); + lookupError = mStorageDelegate->SyncGetKeyValue(GetCompressedFabricId(), key, buffer, size)); // It's ok to not have an entry for the Paired Device list. We treat it the same as having an empty list. if (lookupError != CHIP_ERROR_KEY_NOT_FOUND) @@ -527,7 +525,7 @@ void DeviceController::PersistNextKeyId() if (mStorageDelegate != nullptr && mState == State::Initialized) { uint16_t nextKeyID = mIDAllocator.Peek(); - mStorageDelegate->SyncSetKeyValue(kNextAvailableKeyID, &nextKeyID, sizeof(nextKeyID)); + mStorageDelegate->SyncSetKeyValue(GetCompressedFabricId(), kNextAvailableKeyID, &nextKeyID, sizeof(nextKeyID)); } } @@ -611,7 +609,7 @@ CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params) uint16_t nextKeyID = 0; uint16_t size = sizeof(nextKeyID); - CHIP_ERROR error = mStorageDelegate->SyncGetKeyValue(kNextAvailableKeyID, &nextKeyID, size); + CHIP_ERROR error = mStorageDelegate->SyncGetKeyValue(GetCompressedFabricId(), kNextAvailableKeyID, &nextKeyID, size); if ((error != CHIP_NO_ERROR) || (size != sizeof(nextKeyID))) { nextKeyID = 0; @@ -752,7 +750,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam err = mPairingSession.MessageDispatch().Init(mSystemState->SessionMgr()); SuccessOrExit(err); - device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress, fabric->GetFabricIndex()); + device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress, mFabricIndex); mSystemState->SystemLayer()->StartTimer(kSessionEstablishmentTimeout, OnSessionEstablishmentTimeoutCallback, this); if (params.GetPeerAddress().GetTransportType() != Transport::Type::kBle) @@ -913,7 +911,8 @@ CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) if (mStorageDelegate != nullptr) { - PERSISTENT_KEY_OP(remoteDeviceId, kPairedDeviceKeyPrefix, key, mStorageDelegate->SyncDeleteKeyValue(key)); + PERSISTENT_KEY_OP(remoteDeviceId, kPairedDeviceKeyPrefix, key, + mStorageDelegate->SyncDeleteKeyValue(GetCompressedFabricId(), key)); } mPairedDevices.Remove(remoteDeviceId); @@ -1566,8 +1565,9 @@ void DeviceCommissioner::PersistDeviceList() { mPairedDevices.Serialize([&](ByteSpan data) -> CHIP_ERROR { VerifyOrReturnError(data.size() <= UINT16_MAX, CHIP_ERROR_INVALID_ARGUMENT); - PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, - mStorageDelegate->SyncSetKeyValue(key, data.data(), static_cast(data.size()))); + PERSISTENT_KEY_OP( + static_cast(0), kPairedDeviceListKeyPrefix, key, + mStorageDelegate->SyncSetKeyValue(GetCompressedFabricId(), key, data.data(), static_cast(data.size()))); mPairedDevicesUpdated = false; return CHIP_NO_ERROR; }); diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h index 1808b66caf8813..71e329620ec6c5 100644 --- a/src/controller/CHIPDeviceControllerFactory.h +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -54,7 +54,7 @@ struct SetupParams FabricId fabricId = kUndefinedFabricId; - uint16_t controllerVendorId; + uint16_t controllerVendorId = CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID; // The Device Pairing Delegated used to initialize a Commissioner DevicePairingDelegate * pairingDelegate = nullptr; diff --git a/src/controller/ExampleOperationalCredentialsIssuer.cpp b/src/controller/ExampleOperationalCredentialsIssuer.cpp index 54752fc2c801dd..9932fcdfa4bb23 100644 --- a/src/controller/ExampleOperationalCredentialsIssuer.cpp +++ b/src/controller/ExampleOperationalCredentialsIssuer.cpp @@ -52,14 +52,16 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele Crypto::P256SerializedKeypair serializedKey; uint16_t keySize = static_cast(sizeof(serializedKey)); - if (storage.SyncGetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize) != CHIP_NO_ERROR) + if (storage.SyncGetKeyValue(kUndefinedCompressedFabricId, kOperationalCredentialsIssuerKeypairStorage, &serializedKey, + keySize) != CHIP_NO_ERROR) { // Storage doesn't have an existing keypair. Let's create one and add it to the storage. ReturnErrorOnFailure(mIssuer.Initialize()); ReturnErrorOnFailure(mIssuer.Serialize(serializedKey)); keySize = static_cast(sizeof(serializedKey)); - ReturnErrorOnFailure(storage.SyncSetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize)); + ReturnErrorOnFailure(storage.SyncSetKeyValue(kUndefinedCompressedFabricId, kOperationalCredentialsIssuerKeypairStorage, + &serializedKey, keySize)); } else { @@ -69,15 +71,16 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele keySize = static_cast(sizeof(serializedKey)); - if (storage.SyncGetKeyValue(kOperationalCredentialsIntermediateIssuerKeypairStorage, &serializedKey, keySize) != CHIP_NO_ERROR) + if (storage.SyncGetKeyValue(kUndefinedCompressedFabricId, kOperationalCredentialsIntermediateIssuerKeypairStorage, + &serializedKey, keySize) != CHIP_NO_ERROR) { // Storage doesn't have an existing keypair. Let's create one and add it to the storage. ReturnErrorOnFailure(mIntermediateIssuer.Initialize()); ReturnErrorOnFailure(mIntermediateIssuer.Serialize(serializedKey)); keySize = static_cast(sizeof(serializedKey)); - ReturnErrorOnFailure( - storage.SyncSetKeyValue(kOperationalCredentialsIntermediateIssuerKeypairStorage, &serializedKey, keySize)); + ReturnErrorOnFailure(storage.SyncSetKeyValue( + kUndefinedCompressedFabricId, kOperationalCredentialsIntermediateIssuerKeypairStorage, &serializedKey, keySize)); } else { @@ -107,7 +110,7 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation( uint16_t rcacBufLen = static_cast(std::min(rcac.size(), static_cast(UINT16_MAX))); CHIP_ERROR err = CHIP_NO_ERROR; PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = mStorage->SyncGetKeyValue(key, rcac.data(), rcacBufLen)); + err = mStorage->SyncGetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), rcacBufLen)); if (err == CHIP_NO_ERROR) { // Found root certificate in the storage. @@ -120,8 +123,9 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation( ReturnErrorOnFailure(NewRootX509Cert(rcac_request, mIssuer, rcac)); VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); - PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = mStorage->SyncSetKeyValue(key, rcac.data(), static_cast(rcac.size()))); + PERSISTENT_KEY_OP( + fabricId, kOperationalCredentialsRootCertificateStorage, key, + err = mStorage->SyncSetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), static_cast(rcac.size()))); return err; } diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 3344fc7c5729b8..597f695e969aae 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -76,7 +76,7 @@ CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChainAfterValidation(NodeI uint16_t rcacBufLen = static_cast(std::min(rcac.size(), static_cast(UINT16_MAX))); CHIP_ERROR err = CHIP_NO_ERROR; PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = SyncGetKeyValue(key, rcac.data(), rcacBufLen)); + err = SyncGetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), rcacBufLen)); if (err == CHIP_NO_ERROR) { // Found root certificate in the storage. @@ -90,7 +90,7 @@ CHIP_ERROR AndroidDeviceControllerWrapper::GenerateNOCChainAfterValidation(NodeI VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = SyncSetKeyValue(key, rcac.data(), static_cast(rcac.size()))); + err = SyncSetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), static_cast(rcac.size()))); return err; } @@ -306,13 +306,14 @@ CHIP_ERROR AndroidDeviceControllerWrapper::InitializeOperationalCredentialsIssue // TODO: Use Android keystore system instead of direct storage of private key and add specific errors to check if a specified // item is not found in the keystore. - if (SyncGetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize) != CHIP_NO_ERROR) + if (SyncGetKeyValue(kUndefinedCompressedFabricId, kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize) != + CHIP_NO_ERROR) { // If storage doesn't have an existing keypair, create one and add it to the storage. ReturnErrorOnFailure(mIssuer.Initialize()); ReturnErrorOnFailure(mIssuer.Serialize(serializedKey)); keySize = static_cast(sizeof(serializedKey)); - SyncSetKeyValue(kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize); + SyncSetKeyValue(kUndefinedCompressedFabricId, kOperationalCredentialsIssuerKeypairStorage, &serializedKey, keySize); } else { @@ -328,7 +329,8 @@ void AndroidDeviceControllerWrapper::OnMessage(chip::System::PacketBufferHandle void AndroidDeviceControllerWrapper::OnStatusChange(void) {} -CHIP_ERROR AndroidDeviceControllerWrapper::SyncGetKeyValue(const char * key, void * value, uint16_t & size) +CHIP_ERROR AndroidDeviceControllerWrapper::SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * value, + uint16_t & size) { ChipLogProgress(chipTool, "KVS: Getting key %s", key); @@ -341,13 +343,14 @@ CHIP_ERROR AndroidDeviceControllerWrapper::SyncGetKeyValue(const char * key, voi return err; } -CHIP_ERROR AndroidDeviceControllerWrapper::SyncSetKeyValue(const char * key, const void * value, uint16_t size) +CHIP_ERROR AndroidDeviceControllerWrapper::SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, + const void * value, uint16_t size) { ChipLogProgress(chipTool, "KVS: Setting key %s", key); return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size); } -CHIP_ERROR AndroidDeviceControllerWrapper::SyncDeleteKeyValue(const char * key) +CHIP_ERROR AndroidDeviceControllerWrapper::SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) { ChipLogProgress(chipTool, "KVS: Deleting key %s", key); return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key); diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index fc926e1d27e76a..78174f4429ec2b 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -74,9 +74,10 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel void OnStatusChange(void) override; // PersistentStorageDelegate implementation - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; - CHIP_ERROR SyncDeleteKeyValue(const char * key) override; + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override; + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override; + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override; static AndroidDeviceControllerWrapper * FromJNIHandle(jlong handle) { diff --git a/src/controller/python/ChipDeviceController-StorageDelegate.cpp b/src/controller/python/ChipDeviceController-StorageDelegate.cpp index 608e3ed775c5d7..fced9836e8df17 100644 --- a/src/controller/python/ChipDeviceController-StorageDelegate.cpp +++ b/src/controller/python/ChipDeviceController-StorageDelegate.cpp @@ -29,7 +29,8 @@ namespace chip { namespace Controller { -CHIP_ERROR PythonPersistentStorageDelegate::SyncGetKeyValue(const char * key, void * value, uint16_t & size) +CHIP_ERROR PythonPersistentStorageDelegate::SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * value, + uint16_t & size) { auto val = mStorage.find(key); if (val == mStorage.end()) @@ -61,7 +62,8 @@ CHIP_ERROR PythonPersistentStorageDelegate::SyncGetKeyValue(const char * key, vo return CHIP_NO_ERROR; } -CHIP_ERROR PythonPersistentStorageDelegate::SyncSetKeyValue(const char * key, const void * value, uint16_t size) +CHIP_ERROR PythonPersistentStorageDelegate::SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, + const void * value, uint16_t size) { mStorage[key] = std::string(static_cast(value), size); ChipLogDetail(Controller, "SyncSetKeyValue on %s", key); @@ -69,7 +71,7 @@ CHIP_ERROR PythonPersistentStorageDelegate::SyncSetKeyValue(const char * key, co return CHIP_NO_ERROR; } -CHIP_ERROR PythonPersistentStorageDelegate::SyncDeleteKeyValue(const char * key) +CHIP_ERROR PythonPersistentStorageDelegate::SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) { mStorage.erase(key); return CHIP_NO_ERROR; diff --git a/src/controller/python/ChipDeviceController-StorageDelegate.h b/src/controller/python/ChipDeviceController-StorageDelegate.h index 6cdb870b52ee85..b757dcf8a2a4e9 100644 --- a/src/controller/python/ChipDeviceController-StorageDelegate.h +++ b/src/controller/python/ChipDeviceController-StorageDelegate.h @@ -36,9 +36,10 @@ class PythonPersistentStorageDelegate : public PersistentStorageDelegate { public: PythonPersistentStorageDelegate() {} - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; - CHIP_ERROR SyncDeleteKeyValue(const char * key) override; + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override; + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override; + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override; private: std::map mStorage; diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index ac71588061cc8a..ebd56f04a15e5e 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -38,17 +38,18 @@ class ServerStorageDelegate : public chip::PersistentStorageDelegate { public: CHIP_ERROR - SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override + SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override { return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size); } - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override { return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size); } - CHIP_ERROR SyncDeleteKeyValue(const char * key) override + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override { return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key); } diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h index 70c3431627eecf..8fa55e2471ff0d 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.h @@ -35,7 +35,3 @@ BOOL CHIPIsDevicePaired(uint64_t id); BOOL CHIPGetConnectedDevice(CHIPDeviceConnectionCallback completionHandler); BOOL CHIPGetConnectedDeviceWithID(uint64_t deviceId, CHIPDeviceConnectionCallback completionHandler); void CHIPUnpairDeviceWithID(uint64_t deviceId); - -@interface CHIPToolPersistentStorageDelegate : NSObject - -@end diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m index e9e964dc57874b..2285e8c3d14213 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m @@ -65,12 +65,10 @@ void CHIPSetNextAvailableDeviceID(uint64_t id) CHIPDeviceController * InitializeCHIP(void) { - static CHIPToolPersistentStorageDelegate * storage = nil; static dispatch_once_t onceToken; CHIPDeviceController * controller = [CHIPDeviceController sharedController]; dispatch_once(&onceToken, ^{ - storage = [[CHIPToolPersistentStorageDelegate alloc] init]; - [controller startup:storage vendorId:0 nocSigner:nil]; + [controller startup:nil fabricId:1 vendorId:kCHIPToolTmpVendorId nocSigner:nil]; }); return controller; @@ -117,26 +115,3 @@ void CHIPUnpairDeviceWithID(uint64_t deviceId) NSError * error; [controller unpairDevice:deviceId error:&error]; } - -@implementation CHIPToolPersistentStorageDelegate - -// MARK: CHIPPersistentStorageDelegate - -- (NSString *)CHIPGetKeyValue:(NSString *)key -{ - NSString * value = CHIPGetDomainValueForKey(kCHIPToolDefaultsDomain, key); - NSLog(@"CHIPPersistentStorageDelegate Get Value for Key: %@, value %@", key, value); - return value; -} - -- (void)CHIPSetKeyValue:(NSString *)key value:(NSString *)value -{ - CHIPSetDomainValueForKey(kCHIPToolDefaultsDomain, key, value); -} - -- (void)CHIPDeleteKeyValue:(NSString *)key -{ - CHIPRemoveDomainValueForKey(kCHIPToolDefaultsDomain, key); -} - -@end diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m index dd82722484607c..50ce56e6848264 100644 --- a/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m +++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/Temperature Sensor/TemperatureSensorViewController.m @@ -14,7 +14,6 @@ @interface TemperatureSensorViewController () @property (nonatomic, strong) UILabel * temperatureLabel; @property (nonatomic, strong) UITextField * minIntervalInSecondsTextField; @property (nonatomic, strong) UITextField * maxIntervalInSecondsTextField; -@property (nonatomic, strong) UITextField * deltaInCelsiusTextField; @property (nonatomic, strong) UIButton * sendReportingSetup; @end @@ -51,7 +50,6 @@ - (void)dismissKeyboard { [_minIntervalInSecondsTextField resignFirstResponder]; [_maxIntervalInSecondsTextField resignFirstResponder]; - [_deltaInCelsiusTextField resignFirstResponder]; } - (void)setupUI @@ -119,17 +117,6 @@ - (void)setupUI maxIntervalInSecondsView.translatesAutoresizingMaskIntoConstraints = false; [maxIntervalInSecondsView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; - // Delta - _deltaInCelsiusTextField = [UITextField new]; - _deltaInCelsiusTextField.keyboardType = UIKeyboardTypeNumberPad; - UILabel * deltaInCelsiusLabel = [UILabel new]; - [deltaInCelsiusLabel setText:@"Delta (°C):"]; - UIView * deltaInCelsiusView = [CHIPUIViewUtils viewWithLabel:deltaInCelsiusLabel textField:_deltaInCelsiusTextField]; - [stackView addArrangedSubview:deltaInCelsiusView]; - - deltaInCelsiusView.translatesAutoresizingMaskIntoConstraints = false; - [deltaInCelsiusView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES; - // Reporting button _sendReportingSetup = [UIButton new]; [_sendReportingSetup setTitle:@"Send reporting settings" forState:UIControlStateNormal]; @@ -194,10 +181,8 @@ - (void)reportFromUserEnteredSettings { int minIntervalSeconds = [_minIntervalInSecondsTextField.text intValue]; int maxIntervalSeconds = [_maxIntervalInSecondsTextField.text intValue]; - int deltaInCelsius = [_deltaInCelsiusTextField.text intValue]; - NSLog( - @"Sending temp reporting values: min %@ max %@ value %@", @(minIntervalSeconds), @(maxIntervalSeconds), @(deltaInCelsius)); + NSLog(@"Sending temp reporting values: min %@ max %@ value %@", @(minIntervalSeconds), @(maxIntervalSeconds)); if (CHIPGetConnectedDevice(^(CHIPDevice * _Nullable chipDevice, NSError * _Nullable error) { if (chipDevice) { @@ -207,7 +192,6 @@ - (void)reportFromUserEnteredSettings [cluster subscribeAttributeMeasuredValueWithMinInterval:minIntervalSeconds maxInterval:maxIntervalSeconds - change:deltaInCelsius responseHandler:^(NSError * error, NSDictionary * values) { if (error == nil) return; diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.h b/src/darwin/Framework/CHIP/CHIPDeviceController.h index 04cefbe896e21e..f7d3a34ced44f4 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.h +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.h @@ -97,10 +97,12 @@ typedef void (^CHIPDeviceConnectionCallback)(CHIPDevice * _Nullable device, NSEr * check if the stack needs to be started up. * * @param[in] storageDelegate The delegate for persistent storage + * @param[in] fabricId The fabricId for this controller instance * @param[in] vendorId The vendor ID of the commissioner application * @param[in] nocSigner The CHIPKeypair that is used to generate and sign Node Operational Credentials */ - (BOOL)startup:(_Nullable id)storageDelegate + fabricId:(uint64_t)fabricId vendorId:(uint16_t)vendorId nocSigner:(nullable id)nocSigner; diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index ab8b08a882a2dc..2de018022465ff 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ static NSString * const kErrorGetPairedDevice = @"Failure while trying to retrieve a paired device"; static NSString * const kErrorNotRunning = @"Controller is not running. Call startup first."; static NSString * const kInfoStackShutdown = @"Shutting down the CHIP Stack"; +static NSString * const kErrorCompressedFabricIdGeneration = @"Init failure while generating the Compressed FabricId"; @interface CHIPDeviceController () @@ -64,6 +66,7 @@ @interface CHIPDeviceController () @property (readonly) CHIPP256KeypairBridge keypairBridge; @property (readonly) chip::NodeId localDeviceId; @property (readonly) uint16_t listenPort; +@property (readonly) chip::CompressedFabricId compressedFabricId; @end // TODO Replace Shared Controller with a Controller Factory Singleton @@ -133,6 +136,7 @@ - (BOOL)shutdown } - (BOOL)startup:(_Nullable id)storageDelegate + fabricId:(uint64_t)fabricId vendorId:(uint16_t)vendorId nocSigner:(id)nocSigner { @@ -160,11 +164,21 @@ - (BOOL)startup:(_Nullable id)storageDelegate _keypairBridge.Init(nocSigner); nativeBridge.reset(new chip::Crypto::CHIPP256KeypairNativeBridge(_keypairBridge)); } + errorCode = _operationalCredentialsDelegate->init(_persistentStorageDelegateBridge, std::move(nativeBridge)); if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorOperationalCredentialsInit]) { return; } + uint8_t compressedFabricIdBuf[sizeof(uint64_t)]; + chip::MutableByteSpan compressedFabricIdSpan(compressedFabricIdBuf); + errorCode = chip::Crypto::GenerateCompressedFabricId( + _operationalCredentialsDelegate->GetIssuerPubkey(), fabricId, compressedFabricIdSpan); + _compressedFabricId = chip::Encoding::BigEndian::Get64(compressedFabricIdBuf); + if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCompressedFabricIdGeneration]) { + return; + } + // initialize NodeID if needed [self _getControllerNodeId]; @@ -246,12 +260,14 @@ - (NSNumber *)_getControllerNodeId { uint16_t deviceIdLength = sizeof(_localDeviceId); if (CHIP_NO_ERROR - != _persistentStorageDelegateBridge->SyncGetKeyValue(CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, deviceIdLength)) { + != _persistentStorageDelegateBridge->SyncGetKeyValue( + _compressedFabricId, CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, deviceIdLength)) { _localDeviceId = arc4random(); _localDeviceId = _localDeviceId << 32 | arc4random(); CHIP_LOG_ERROR("Assigned %llx node ID to the controller", _localDeviceId); - _persistentStorageDelegateBridge->SyncSetKeyValue(CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, sizeof(_localDeviceId)); + _persistentStorageDelegateBridge->SyncSetKeyValue( + _compressedFabricId, CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, sizeof(_localDeviceId)); } else { CHIP_LOG_ERROR("Found %llx node ID for the controller", _localDeviceId); } diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h index 1edb35a9076b10..cf3da925518fcb 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h @@ -50,6 +50,8 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC void SetDeviceID(chip::NodeId deviceId) { mDeviceBeingPaired = deviceId; } void ResetDeviceID() { mDeviceBeingPaired = chip::kUndefinedNodeId; } + const chip::Crypto::P256PublicKey & GetIssuerPubkey() { return mIssuerKey->Pubkey(); }; + CHIP_ERROR GenerateNOCChainAfterValidation(chip::NodeId nodeId, chip::FabricId fabricId, const chip::Crypto::P256PublicKey & pubkey, chip::MutableByteSpan & rcac, chip::MutableByteSpan & icac, chip::MutableByteSpan & noc); diff --git a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm index f56795af9052bf..32dd3830de867f 100644 --- a/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm +++ b/src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm @@ -86,10 +86,11 @@ static BOOL isRunningTests(void) char issuerIdString[16]; uint16_t idStringLen = sizeof(issuerIdString); - if (CHIP_NO_ERROR != storage->SyncGetKeyValue(CHIP_COMMISSIONER_CA_ISSUER_ID, issuerIdString, idStringLen)) { + if (CHIP_NO_ERROR + != storage->SyncGetKeyValue(kUndefinedCompressedFabricId, CHIP_COMMISSIONER_CA_ISSUER_ID, issuerIdString, idStringLen)) { mIssuerId = arc4random(); CHIP_LOG_ERROR("Assigned %d certificate issuer ID to the commissioner", mIssuerId); - storage->SyncSetKeyValue(CHIP_COMMISSIONER_CA_ISSUER_ID, &mIssuerId, sizeof(mIssuerId)); + storage->SyncSetKeyValue(kUndefinedCompressedFabricId, CHIP_COMMISSIONER_CA_ISSUER_ID, &mIssuerId, sizeof(mIssuerId)); } else { CHIP_LOG_ERROR("Found %d certificate issuer ID for the commissioner", mIssuerId); } @@ -208,7 +209,7 @@ static BOOL isRunningTests(void) CHIP_ERROR err = CHIP_NO_ERROR; if (!mGenerateRootCert) { PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = mStorage->SyncGetKeyValue(key, rcac.data(), rcacBufLen)); + err = mStorage->SyncGetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), rcacBufLen)); if (err == CHIP_NO_ERROR) { // Found root certificate in the storage. rcac.reduce_size(rcacBufLen); @@ -221,7 +222,7 @@ static BOOL isRunningTests(void) VerifyOrReturnError(CanCastTo(rcac.size()), CHIP_ERROR_INTERNAL); PERSISTENT_KEY_OP(fabricId, kOperationalCredentialsRootCertificateStorage, key, - err = mStorage->SyncSetKeyValue(key, rcac.data(), static_cast(rcac.size()))); + err = mStorage->SyncSetKeyValue(kUndefinedCompressedFabricId, key, rcac.data(), static_cast(rcac.size()))); mGenerateRootCert = false; diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h index 93111fe49a5481..1a3904f41c5092 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h @@ -20,7 +20,12 @@ NS_ASSUME_NONNULL_BEGIN /** - * The protocol definition for the CHIPPersistenStorageDelegate + * The protocol definition for the CHIPPersistentStorageDelegate + * Storage is expected to be split across different CompressedFabricIds. + * CHIP stores most of its operational data inside a "Fabric" scope with a handful + * of metadata items in the "global" scope + * + * A Compressed FabricId of "0" indicates the "global" scope for storage. * * All delegate methods will be called on the supplied Delegate Queue. */ @@ -31,19 +36,19 @@ NS_ASSUME_NONNULL_BEGIN * Get the value for the given key * */ -- (nullable NSString *)CHIPGetKeyValue:(NSString *)key; +- (nullable NSString *)CHIPGetKeyValueForFabric:(NSNumber *)CompressedFabricId key:(NSString *)key; /** * Set the value of the key to the given value * */ -- (void)CHIPSetKeyValue:(NSString *)key value:(NSString *)value; +- (void)CHIPSetKeyValueForFabric:(NSNumber *)CompressedFabricId key:(NSString *)key value:(NSString *)value; /** * Delete the key and corresponding value * */ -- (void)CHIPDeleteKeyValue:(NSString *)key; +- (void)CHIPDeleteKeyValueForFabric:(NSNumber *)CompressedFabricId key:(NSString *)key; @end diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h index 17175fce4514c1..57486ec3fb8dcf 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h @@ -30,11 +30,12 @@ class CHIPPersistentStorageDelegateBridge : public chip::PersistentStorageDelega void setFrameworkDelegate(_Nullable id delegate); - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override; + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override; - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override; + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override; - CHIP_ERROR SyncDeleteKeyValue(const char * key) override; + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override; private: id mDelegate; diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm index 94ad61c5ebfc6d..5817682408df8c 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm @@ -71,7 +71,8 @@ }); } -CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) +CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncGetKeyValue( + const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) { __block CHIP_ERROR error = CHIP_NO_ERROR; NSString * keyString = [NSString stringWithUTF8String:key]; @@ -82,10 +83,12 @@ NSString * valueString = nil; id strongDelegate = mDelegate; + NSNumber * compressedFabricId = [NSNumber numberWithUnsignedLongLong:fabricId]; if (strongDelegate) { - valueString = [strongDelegate CHIPGetKeyValue:keyString]; + valueString = [strongDelegate CHIPGetKeyValueForFabric:compressedFabricId key:keyString]; } else { - valueString = [mDefaultPersistentStorage objectForKey:keyString]; + NSDictionary * fabricStorage = [mDefaultPersistentStorage objectForKey:[compressedFabricId stringValue]]; + valueString = [fabricStorage valueForKey:keyString]; } if (valueString != nil) { @@ -111,7 +114,8 @@ return error; } -CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncSetKeyValue(const char * key, const void * value, uint16_t size) +CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncSetKeyValue( + const chip::CompressedFabricId fabricId, const char * key, const void * value, uint16_t size) { std::string base64Value = StringToBase64(std::string(static_cast(value), size)); @@ -122,10 +126,17 @@ NSLog(@"PersistentStorageDelegate Set Key %@", keyString); id strongDelegate = mDelegate; + NSNumber * compressedFabricId = [NSNumber numberWithUnsignedLongLong:fabricId]; if (strongDelegate) { - [strongDelegate CHIPSetKeyValue:keyString value:valueString]; + [strongDelegate CHIPSetKeyValueForFabric:compressedFabricId key:keyString value:valueString]; } else { - [mDefaultPersistentStorage setObject:valueString forKey:keyString]; + NSMutableDictionary * fabricStorage = + [[mDefaultPersistentStorage objectForKey:[compressedFabricId stringValue]] mutableCopy]; + if (!fabricStorage) { + fabricStorage = [[NSMutableDictionary alloc] init]; + } + [fabricStorage setObject:valueString forKey:keyString]; + [mDefaultPersistentStorage setObject:fabricStorage forKey:[compressedFabricId stringValue]]; } }); @@ -136,17 +147,27 @@ return CHIP_NO_ERROR; } -CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncDeleteKeyValue(const char * key) +CHIP_ERROR CHIPPersistentStorageDelegateBridge::SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) { NSString * keyString = [NSString stringWithUTF8String:key]; dispatch_sync(mWorkQueue, ^{ NSLog(@"PersistentStorageDelegate Delete Key: %@", keyString); id strongDelegate = mDelegate; + NSNumber * compressedFabricId = [NSNumber numberWithUnsignedLongLong:fabricId]; if (strongDelegate) { - [strongDelegate CHIPDeleteKeyValue:keyString]; + [strongDelegate CHIPDeleteKeyValueForFabric:compressedFabricId key:keyString]; } else { - [mDefaultPersistentStorage removeObjectForKey:keyString]; + NSMutableDictionary * fabricStorage = + [[mDefaultPersistentStorage objectForKey:[compressedFabricId stringValue]] mutableCopy]; + if (fabricStorage) { + [fabricStorage removeObjectForKey:keyString]; + if (fabricStorage.count == 0) { + [mDefaultPersistentStorage removeObjectForKey:[compressedFabricId stringValue]]; + } else { + [mDefaultPersistentStorage setObject:fabricStorage forKey:[compressedFabricId stringValue]]; + } + } } }); diff --git a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt index b5c3138569007f..9a92aff7f987ba 100644 --- a/src/darwin/Framework/CHIP/templates/clusters-tests.zapt +++ b/src/darwin/Framework/CHIP/templates/clusters-tests.zapt @@ -85,7 +85,7 @@ CHIPDevice * GetPairedDevice(uint64_t deviceId) [controller setListenPort:kLocalPort]; [controller setPairingDelegate:pairing queue:callbackQueue]; - BOOL started = [controller startup:nil vendorId:0 nocSigner:nil]; + BOOL started = [controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]; XCTAssertTrue(started); NSError * error; diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index b48787b9a25dd9..d28e512d57efa7 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -103,7 +103,7 @@ - (void)testInitStack [controller setListenPort:kLocalPort]; [controller setPairingDelegate:pairing queue:callbackQueue]; - BOOL started = [controller startup:nil vendorId:0 nocSigner:nil]; + BOOL started = [controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]; XCTAssertTrue(started); NSError * error; diff --git a/src/darwin/Framework/CHIPTests/CHIPControllerTests.m b/src/darwin/Framework/CHIPTests/CHIPControllerTests.m index 82dd31e62a09a0..1864702a4e00aa 100644 --- a/src/darwin/Framework/CHIPTests/CHIPControllerTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPControllerTests.m @@ -32,11 +32,11 @@ @implementation CHIPControllerTests - (void)testControllerLifecycle { CHIPDeviceController * controller = [CHIPDeviceController sharedController]; - XCTAssertTrue([controller startup:nil vendorId:0 nocSigner:nil]); + XCTAssertTrue([controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]); XCTAssertTrue([controller shutdown]); // now try to restart the controller - XCTAssertTrue([controller startup:nil vendorId:0 nocSigner:nil]); + XCTAssertTrue([controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]); XCTAssertTrue([controller shutdown]); } @@ -44,7 +44,7 @@ - (void)testControllerMultipleStartup { CHIPDeviceController * controller = [CHIPDeviceController sharedController]; for (int i = 0; i < 5; i++) { - XCTAssertTrue([controller startup:nil vendorId:0 nocSigner:nil]); + XCTAssertTrue([controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]); } XCTAssertTrue([controller shutdown]); } @@ -52,7 +52,7 @@ - (void)testControllerMultipleStartup - (void)testControllerMultipleShutdown { CHIPDeviceController * controller = [CHIPDeviceController sharedController]; - XCTAssertTrue([controller startup:nil vendorId:0 nocSigner:nil]); + XCTAssertTrue([controller startup:nil fabricId:1 vendorId:0 nocSigner:nil]); for (int i = 0; i < 5; i++) { XCTAssertTrue([controller shutdown]); } diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index 5c07ad56e18601..bd663a894272a9 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -2207,6 +2207,16 @@ using CHIP_ERROR = ::chip::ChipError; */ #define CHIP_ERROR_IM_STATUS_CODE_RECEIVED CHIP_CORE_ERROR(0xca) +/** + * @def CHIP_ERROR_ALREADY_EXISTS + * + * @brief + * The addition of a new item failed because it an existing item was found + * and the container doesn't support overwriting items. + * + */ +#define CHIP_ERROR_ALREADY_EXISTS CHIP_CORE_ERROR(0xca) + /** * @} */ diff --git a/src/lib/core/CHIPPersistentStorageDelegate.h b/src/lib/core/CHIPPersistentStorageDelegate.h index eca9a40fd75c27..c0c4d81149b6c8 100644 --- a/src/lib/core/CHIPPersistentStorageDelegate.h +++ b/src/lib/core/CHIPPersistentStorageDelegate.h @@ -19,10 +19,20 @@ #pragma once #include +#include #include namespace chip { +/** + * @brief The Persistent Storage Delegate provides a Fabric scoped storage + * interface for the CHIP stack to store items. + * + * The FabricId used here allows for storage to reuse keys within each fabric's scope + * These APIs might be called with `kUndefinedCompressedFabricId` in which case + * The delegate is expected to access a "global" storage scope. + * + */ class DLL_EXPORT PersistentStorageDelegate { public: @@ -38,7 +48,7 @@ class DLL_EXPORT PersistentStorageDelegate * Caller is responsible to take care of any special formatting needs (e.g. byte * order, null terminators, consistency checks or versioning). * - * + * @param[in] fabricId The compressed Fabric Id where this key is stored * @param[in] key Key to lookup * @param[out] buffer Value for the key * @param[in, out] size Input value buffer size, output length of value. @@ -46,25 +56,27 @@ class DLL_EXPORT PersistentStorageDelegate * such cases, the user should allocate the buffer large * enough (>= output length), and call the API again. */ - virtual CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) = 0; + virtual CHIP_ERROR SyncGetKeyValue(const CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) = 0; /** * @brief * Set the value for the key to a byte buffer. * + * @param[in] fabricId The compressed Fabric Id where this key should be stored * @param[in] key Key to be set * @param[in] value Value to be set * @param[in] size Size of the Value */ - virtual CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) = 0; + virtual CHIP_ERROR SyncSetKeyValue(const CompressedFabricId fabricId, const char * key, const void * value, uint16_t size) = 0; /** * @brief * Deletes the value for the key * + * @param[in] fabricId The compressed Fabric Id where this key is stored * @param[in] key Key to be deleted */ - virtual CHIP_ERROR SyncDeleteKeyValue(const char * key) = 0; + virtual CHIP_ERROR SyncDeleteKeyValue(const CompressedFabricId fabricId, const char * key) = 0; }; } // namespace chip diff --git a/src/protocols/secure_channel/tests/TestCASESession.cpp b/src/protocols/secure_channel/tests/TestCASESession.cpp index d18adfbb33a8e2..56941967372ece 100644 --- a/src/protocols/secure_channel/tests/TestCASESession.cpp +++ b/src/protocols/secure_channel/tests/TestCASESession.cpp @@ -281,7 +281,7 @@ class TestPersistentStorageDelegate : public PersistentStorageDelegate } } - CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override + CHIP_ERROR SyncGetKeyValue(const chip::CompressedFabricId fabricId, const char * key, void * buffer, uint16_t & size) override { for (int i = 0; i < 16; i++) { @@ -298,7 +298,8 @@ class TestPersistentStorageDelegate : public PersistentStorageDelegate return CHIP_ERROR_INTERNAL; } - CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override + CHIP_ERROR SyncSetKeyValue(const chip::CompressedFabricId fabricId, const char * key, const void * value, + uint16_t size) override { for (int i = 0; i < 16; i++) { @@ -317,7 +318,7 @@ class TestPersistentStorageDelegate : public PersistentStorageDelegate return CHIP_ERROR_INTERNAL; } - CHIP_ERROR SyncDeleteKeyValue(const char * key) override { return CHIP_NO_ERROR; } + CHIP_ERROR SyncDeleteKeyValue(const chip::CompressedFabricId fabricId, const char * key) override { return CHIP_NO_ERROR; } private: char * keys[16]; diff --git a/src/transport/FabricTable.cpp b/src/transport/FabricTable.cpp index d31f09f0ca3751..430f5f1e7da069 100644 --- a/src/transport/FabricTable.cpp +++ b/src/transport/FabricTable.cpp @@ -51,6 +51,8 @@ CHIP_ERROR FabricInfo::StoreIntoKVS(PersistentStorageDelegate * kvs) StorableFabricInfo * info = chip::Platform::New(); ReturnErrorCodeIf(info == nullptr, CHIP_ERROR_NO_MEMORY); + uint64_t storableFabricId = Encoding::LittleEndian::HostSwap64(mOperationalId.GetCompressedFabricId()); + info->mNodeId = Encoding::LittleEndian::HostSwap64(mOperationalId.GetNodeId()); info->mFabric = Encoding::LittleEndian::HostSwap16(mFabric); info->mVendorId = Encoding::LittleEndian::HostSwap16(mVendorId); @@ -105,7 +107,11 @@ CHIP_ERROR FabricInfo::StoreIntoKVS(PersistentStorageDelegate * kvs) memcpy(info->mNOCCert, mNOCCert.data(), mNOCCert.size()); } - err = kvs->SyncSetKeyValue(key, info, sizeof(StorableFabricInfo)); + // Store the Fabric metadata in the global scope + SuccessOrExit(err = kvs->SyncSetKeyValue(kUndefinedCompressedFabricId, key, &storableFabricId, sizeof(storableFabricId))); + + // Store the Fabric info in the fabric scope + err = kvs->SyncSetKeyValue(mOperationalId.GetCompressedFabricId(), key, info, sizeof(StorableFabricInfo)); if (err != CHIP_NO_ERROR) { ChipLogError(Discovery, "Error occurred calling SyncSetKeyValue: %s", chip::ErrorStr(err)); @@ -136,7 +142,15 @@ CHIP_ERROR FabricInfo::FetchFromKVS(PersistentStorageDelegate * kvs) NodeId nodeId; - SuccessOrExit(err = kvs->SyncGetKeyValue(key, info, infoSize)); + CompressedFabricId fabricId = kUndefinedCompressedFabricId; + uint64_t storedFabricId = kUndefinedCompressedFabricId; + uint16_t storedFabricIdSize = sizeof(storedFabricId); + // First Load the Compressed Fabric Id + SuccessOrExit(err = kvs->SyncGetKeyValue(kUndefinedCompressedFabricId, key, &storedFabricId, storedFabricIdSize)); + fabricId = Encoding::LittleEndian::HostSwap64(storedFabricId); + + // Load the stored Fabric Info from the Fabric scoped storage + SuccessOrExit(err = kvs->SyncGetKeyValue(fabricId, key, info, infoSize)); mFabricId = Encoding::LittleEndian::HostSwap64(info->mFabricId); nodeId = Encoding::LittleEndian::HostSwap64(info->mNodeId); @@ -203,10 +217,28 @@ CHIP_ERROR FabricInfo::DeleteFromKVS(PersistentStorageDelegate * kvs, FabricInde { CHIP_ERROR err = CHIP_NO_ERROR; + uint64_t storedFabricId = kUndefinedCompressedFabricId; + uint16_t storedFabricIdSize = sizeof(storedFabricId); char key[kKeySize]; ReturnErrorOnFailure(GenerateKey(id, key, sizeof(key))); - err = kvs->SyncDeleteKeyValue(key); + err = kvs->SyncGetKeyValue(kUndefinedCompressedFabricId, key, &storedFabricId, storedFabricIdSize); + if (err != CHIP_NO_ERROR) + { + ChipLogDetail(Discovery, "Fabric %d is not yet configured", id); + return err; + } + CompressedFabricId fabricId = Encoding::LittleEndian::HostSwap64(storedFabricId); + + // delete the global key + err = kvs->SyncDeleteKeyValue(kUndefinedCompressedFabricId, key); + if (err != CHIP_NO_ERROR) + { + ChipLogDetail(Discovery, "Failed to delete global key for Fabric %d", id); + } + + // delete the fabric scoped key + err = kvs->SyncDeleteKeyValue(fabricId, key); if (err != CHIP_NO_ERROR) { ChipLogDetail(Discovery, "Fabric %d is not yet configured", id); @@ -384,6 +416,27 @@ FabricInfo * FabricTable::FindFabricWithIndex(FabricIndex fabricIndex) return nullptr; } +FabricInfo * FabricTable::FindFabricWithCompressedId(CompressedFabricId fabricId) +{ + if (fabricId == kUndefinedCompressedFabricId) + { + return nullptr; + } + + static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX"); + for (FabricIndex i = kMinValidFabricIndex; i <= kMaxValidFabricIndex; i++) + { + FabricInfo * fabric = FindFabricWithIndex(i); + + if (fabric != nullptr && fabricId == fabric->GetPeerId().GetCompressedFabricId()) + { + LoadFromStorage(fabric); + return fabric; + } + } + return nullptr; +} + void FabricTable::Reset() { static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX"); @@ -438,6 +491,21 @@ CHIP_ERROR FabricTable::LoadFromStorage(FabricInfo * fabric) return CHIP_NO_ERROR; } +CHIP_ERROR FabricInfo::Populate() +{ + P256PublicKey pubkey; + ValidationContext validContext; + validContext.Reset(); + validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature); + validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth); + + ChipLogProgress(Discovery, "Verifying the received credentials"); + ReturnErrorOnFailure(VerifyCredentials(mNOCCert, mICACert, validContext, mOperationalId, mFabricId, pubkey)); + ChipLogProgress(Discovery, "Assigned compressed fabric ID: 0x" ChipLogFormatX64 ", node ID: 0x" ChipLogFormatX64, + ChipLogValueX64(mOperationalId.GetCompressedFabricId()), ChipLogValueX64(mOperationalId.GetNodeId())); + return CHIP_NO_ERROR; +} + CHIP_ERROR FabricInfo::SetFabricInfo(FabricInfo & newFabric) { P256PublicKey pubkey; @@ -463,6 +531,27 @@ CHIP_ERROR FabricInfo::SetFabricInfo(FabricInfo & newFabric) return CHIP_NO_ERROR; } +bool FabricInfo::Matches(const FabricInfo * info) const +{ + if (info == nullptr) + { + return false; + } + + ByteSpan certSpan; + CHIP_ERROR err = info->GetRootCert(certSpan); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Discovery, "Unable to get root cert while comparing fabric info"); + return false; + } + bool rootCertMatches = mRootCert.data_equal(certSpan); + bool metadataMatches = GetFabricId() == info->GetFabricId() && GetVendorId() == info->GetVendorId() && + GetCompressedFabricId() == info->GetCompressedFabricId() && GetPeerId() == info->GetPeerId(); + + return metadataMatches && rootCertMatches; +} + FabricIndex FabricTable::FindDestinationIDCandidate(const ByteSpan & destinationId, const ByteSpan & initiatorRandom, const ByteSpan * ipkList, size_t ipkListEntries) { @@ -484,6 +573,22 @@ CHIP_ERROR FabricTable::AddNewFabric(FabricInfo & newFabric, FabricIndex * outpu { VerifyOrReturnError(outputIndex != nullptr, CHIP_ERROR_INVALID_ARGUMENT); static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX"); + + // Make sure the fabric info is fully initialized + ReturnErrorOnFailure(newFabric.Populate()); + CompressedFabricId compressedFabricId = newFabric.GetCompressedFabricId(); + FabricInfo * existingInfo = FindFabricWithCompressedId(compressedFabricId); + if (newFabric.Matches(existingInfo)) + { + *outputIndex = existingInfo->GetFabricIndex(); + return CHIP_NO_ERROR; + } + else if (existingInfo != nullptr) + { + ChipLogError(Discovery, "Cannot update existing fabric, reset fabric storage."); + return CHIP_ERROR_ALREADY_EXISTS; + } + for (FabricIndex i = mNextAvailableFabricIndex; i <= kMaxValidFabricIndex; i++) { FabricInfo * fabric = FindFabricWithIndex(i); diff --git a/src/transport/FabricTable.h b/src/transport/FabricTable.h index e2d3e618eb6036..444458b88fd0e4 100644 --- a/src/transport/FabricTable.h +++ b/src/transport/FabricTable.h @@ -87,6 +87,7 @@ class DLL_EXPORT FabricInfo FabricId GetFabricId() const { return mFabricId; } FabricIndex GetFabricIndex() const { return mFabric; } uint16_t GetVendorId() const { return mVendorId; } + CompressedFabricId GetCompressedFabricId() const { return mOperationalId.GetCompressedFabricId(); } void SetVendorId(uint16_t vendorId) { mVendorId = vendorId; } @@ -121,23 +122,25 @@ class DLL_EXPORT FabricInfo CHIP_ERROR MatchDestinationID(const ByteSpan & destinationId, const ByteSpan & initiatorRandom, const ByteSpan * ipkList, size_t ipkListEntries); + bool Matches(const FabricInfo * info) const; + // TODO - Refactor storing and loading of fabric info from persistent storage. // The op cert array doesn't need to be in RAM except when it's being // transmitted to peer node during CASE session setup. - CHIP_ERROR GetRootCert(ByteSpan & cert) + CHIP_ERROR GetRootCert(ByteSpan & cert) const { ReturnErrorCodeIf(mRootCert.empty(), CHIP_ERROR_INCORRECT_STATE); cert = mRootCert; return CHIP_NO_ERROR; } - CHIP_ERROR GetICACert(ByteSpan & cert) + CHIP_ERROR GetICACert(ByteSpan & cert) const { cert = mICACert; return CHIP_NO_ERROR; } - CHIP_ERROR GetNOCCert(ByteSpan & cert) + CHIP_ERROR GetNOCCert(ByteSpan & cert) const { ReturnErrorCodeIf(mNOCCert.empty(), CHIP_ERROR_INCORRECT_STATE); cert = mNOCCert; @@ -178,6 +181,8 @@ class DLL_EXPORT FabricInfo ReleaseOperationalCerts(); } + CHIP_ERROR Populate(); + CHIP_ERROR SetFabricInfo(FabricInfo & fabric); /* Generate a compressed peer ID (containing compressed fabric ID) using provided fabric ID, node ID and @@ -356,6 +361,7 @@ class DLL_EXPORT FabricTable void ReleaseFabricIndex(FabricIndex fabricIndex); + FabricInfo * FindFabricWithCompressedId(CompressedFabricId fabricId); FabricInfo * FindFabricWithIndex(FabricIndex fabricIndex); FabricIndex FindDestinationIDCandidate(const ByteSpan & destinationId, const ByteSpan & initiatorRandom,