diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 35e18361877638..5ea1bd89a8a437 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index cab04724648e52..d34ffdc5b59dde 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -42,7 +42,7 @@ client cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } @@ -104,7 +104,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/door-lock-app/door-lock-common/door-lock-app.matter b/examples/door-lock-app/door-lock-common/door-lock-app.matter index 547b7ae2fe7913..6192710b913d11 100644 --- a/examples/door-lock-app/door-lock-common/door-lock-app.matter +++ b/examples/door-lock-app/door-lock-common/door-lock-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index b695f7f9577756..29f7f291554502 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index b81d7297eacdea..fbb26b4dc88dde 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 054c4fda4ae105..c61d9b618bdeda 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/log-source-app/log-source-common/log-source-app.matter b/examples/log-source-app/log-source-common/log-source-app.matter index f39b90213f7e03..5c65c053a513f3 100644 --- a/examples/log-source-app/log-source-common/log-source-app.matter +++ b/examples/log-source-app/log-source-common/log-source-app.matter @@ -37,7 +37,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter index 4f3207eb3a79a1..90ed5718260529 100644 --- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter +++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter @@ -42,7 +42,7 @@ client cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } @@ -104,7 +104,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter index 107bf6e381472c..fdb5c8665f5f84 100644 --- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter +++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter index db3d9718d74a81..e5a620028c9f84 100644 --- a/examples/pump-app/pump-common/pump-app.matter +++ b/examples/pump-app/pump-common/pump-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter index 430bc8d07b789f..0fbe39a5c5e782 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter index 765ed9c0ea9fb7..1913689175cca9 100644 --- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter +++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter index b67e43bdb72c83..17a2d05b3403a2 100644 --- a/examples/thermostat/thermostat-common/thermostat.matter +++ b/examples/thermostat/thermostat-common/thermostat.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 1f241f096c0f22..7c8c46e3a9473a 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index a4ec6430b37463..ceb5b00a2b160a 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 0f8fa24967e1a9..e23c65ca32c3bb 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -42,7 +42,7 @@ server cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/src/app/clusters/access-control-server/access-control-server.cpp b/src/app/clusters/access-control-server/access-control-server.cpp index 19b17d4406093f..61f639673f59eb 100644 --- a/src/app/clusters/access-control-server/access-control-server.cpp +++ b/src/app/clusters/access-control-server/access-control-server.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,12 @@ using namespace chip::Access; namespace AccessControlCluster = chip::app::Clusters::AccessControl; +// TODO(#13590): generated code doesn't automatically handle max length so do it manually +constexpr int kExtensionDataMaxLength = 128; + +// Storage version used in keys. +constexpr int kStorageVersion = 1; + namespace { struct Subject @@ -355,7 +362,7 @@ class AccessControlAttribute : public chip::app::AttributeAccessInterface CHIP_ERROR ReadAcl(AttributeValueEncoder & aEncoder); CHIP_ERROR ReadExtension(AttributeValueEncoder & aEncoder); CHIP_ERROR WriteAcl(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder); - CHIP_ERROR WriteExtension(AttributeValueDecoder & aDecoder); + CHIP_ERROR WriteExtension(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder); }; constexpr uint16_t AccessControlAttribute::ClusterRevision; @@ -476,7 +483,28 @@ CHIP_ERROR AccessControlAttribute::ReadAcl(AttributeValueEncoder & aEncoder) CHIP_ERROR AccessControlAttribute::ReadExtension(AttributeValueEncoder & aEncoder) { - return aEncoder.EncodeEmptyList(); + auto & storage = Server::GetInstance().GetPersistentStorage(); + DefaultStorageKeyAllocator key; + + auto & fabrics = Server::GetInstance().GetFabricTable(); + + return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR { + for (auto it = fabrics.begin(); it != fabrics.end(); ++it) + { + uint8_t buffer[kExtensionDataMaxLength] = { 0 }; + uint16_t size = static_cast(sizeof(buffer)); + auto err = + storage.SyncGetKeyValue(key.AccessControlExtensionEntry(kStorageVersion, it->GetFabricIndex()), buffer, size); + ReturnErrorCodeIf(err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR); + ReturnErrorOnFailure(err); + AccessControlCluster::Structs::ExtensionEntry::Type item = { + .data = ByteSpan(buffer, size), + .fabricIndex = it->GetFabricIndex(), + }; + ReturnErrorOnFailure(encoder.Encode(item)); + } + return CHIP_NO_ERROR; + }); } CHIP_ERROR AccessControlAttribute::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) @@ -486,7 +514,7 @@ CHIP_ERROR AccessControlAttribute::Write(const ConcreteDataAttributePath & aPath case AccessControlCluster::Attributes::Acl::Id: return WriteAcl(aPath, aDecoder); case AccessControlCluster::Attributes::Extension::Id: - return WriteExtension(aDecoder); + return WriteExtension(aPath, aDecoder); } return CHIP_NO_ERROR; @@ -570,10 +598,65 @@ CHIP_ERROR AccessControlAttribute::WriteAcl(const ConcreteDataAttributePath & aP return CHIP_NO_ERROR; } -CHIP_ERROR AccessControlAttribute::WriteExtension(AttributeValueDecoder & aDecoder) +CHIP_ERROR AccessControlAttribute::WriteExtension(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) { - DataModel::DecodableList list; - ReturnErrorOnFailure(aDecoder.Decode(list)); + auto & storage = Server::GetInstance().GetPersistentStorage(); + DefaultStorageKeyAllocator key; + + FabricIndex accessingFabricIndex = aDecoder.AccessingFabricIndex(); + + if (!aPath.IsListItemOperation()) + { + DataModel::DecodableList list; + ReturnErrorOnFailure(aDecoder.Decode(list)); + + size_t count = 0; + ReturnErrorOnFailure(list.ComputeSize(&count)); + + if (count == 0) + { + auto err = storage.SyncDeleteKeyValue(key.AccessControlExtensionEntry(kStorageVersion, accessingFabricIndex)); + ReturnErrorCodeIf(err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, err); + } + else if (count == 1) + { + auto iterator = list.begin(); + ReturnErrorCodeIf(!iterator.Next(), CHIP_ERROR_MISSING_TLV_ELEMENT); + auto & item = iterator.GetValue(); + // TODO(#13590): generated code doesn't automatically handle max length so do it manually + ReturnErrorCodeIf(item.data.size() > kExtensionDataMaxLength, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(storage.SyncSetKeyValue(key.AccessControlExtensionEntry(kStorageVersion, accessingFabricIndex), + item.data.data(), static_cast(item.data.size()))); + } + else + { + // Only one item supported per fabric. + return CHIP_ERROR_INVALID_ARGUMENT; + } + } + else if (aPath.mListOp == ConcreteDataAttributePath::ListOperation::AppendItem) + { + { + uint8_t buffer[0]; + uint16_t size = static_cast(sizeof(buffer)); + auto err = + storage.SyncGetKeyValue(key.AccessControlExtensionEntry(kStorageVersion, accessingFabricIndex), buffer, size); + ReturnErrorCodeIf(err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, err); + } + + AccessControlCluster::Structs::ExtensionEntry::DecodableType item; + ReturnErrorOnFailure(aDecoder.Decode(item)); + ChipLogProgress(DataManagement, "############################ storing item %u", (unsigned) item.data.size()); + // TODO(#13590): generated code doesn't automatically handle max length so do it manually + ReturnErrorCodeIf(item.data.size() > kExtensionDataMaxLength, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(storage.SyncSetKeyValue(key.AccessControlExtensionEntry(kStorageVersion, accessingFabricIndex), + item.data.data(), static_cast(item.data.size()))); + } + else + { + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + return CHIP_NO_ERROR; } diff --git a/src/app/zap-templates/zcl/data-model/chip/access-control-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/access-control-cluster.xml index fa7d0eb82254ce..561925936784dc 100644 --- a/src/app/zap-templates/zcl/data-model/chip/access-control-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/access-control-cluster.xml @@ -58,8 +58,8 @@ limitations under the License. - - + + diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 2f110836cd057d..688c4d0ad69705 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -42,7 +42,7 @@ client cluster AccessControl = 31 { } struct ExtensionEntry { - OCTET_STRING<254> data = 1; + OCTET_STRING<128> data = 1; fabric_idx fabricIndex = 254; } diff --git a/src/lib/support/DefaultStorageKeyAllocator.h b/src/lib/support/DefaultStorageKeyAllocator.h index 3bbc29007ac6c2..ccaa5e2c5c0570 100644 --- a/src/lib/support/DefaultStorageKeyAllocator.h +++ b/src/lib/support/DefaultStorageKeyAllocator.h @@ -45,7 +45,11 @@ class DefaultStorageKeyAllocator // FailSafeContext const char * FailSafeContextKey() { return Format("g/fsc"); } - // Access Control List + // Access Control + const char * AccessControlExtensionEntry(size_t version, FabricIndex fabric) + { + return Format("a/%x/1/%x", static_cast(version), static_cast(fabric)); + } const char * AccessControlList() { return Format("acl"); } const char * AccessControlEntry(size_t index) diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index 896d137b6ee1bf..d462d03636fb60 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -4683,9 +4683,13 @@ CHIP_ERROR Type::EncodeForRead(TLV::TLVWriter & writer, TLV::Tag tag, FabricInde CHIP_ERROR Type::DoEncode(TLV::TLVWriter & writer, TLV::Tag tag, const Optional & accessingFabricIndex) const { + bool includeSensitive = !accessingFabricIndex.HasValue() || (accessingFabricIndex.Value() == fabricIndex); TLV::TLVType outer; ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer)); - ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kData)), data)); + if (includeSensitive) + { + ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kData)), data)); + } if (accessingFabricIndex.HasValue()) { ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kFabricIndex)), fabricIndex));