From 32db858cccf56bb37ef64b3b3a702ebe374700a1 Mon Sep 17 00:00:00 2001 From: Jim Buzbee Date: Fri, 10 Mar 2023 15:17:50 -0700 Subject: [PATCH 1/5] Initial push of Group Key Management Cluster --- .../cluster/GroupKeyManagementCluster.ts | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/matter/cluster/GroupKeyManagementCluster.ts diff --git a/src/matter/cluster/GroupKeyManagementCluster.ts b/src/matter/cluster/GroupKeyManagementCluster.ts new file mode 100644 index 0000000..0f94adf --- /dev/null +++ b/src/matter/cluster/GroupKeyManagementCluster.ts @@ -0,0 +1,135 @@ +/** + * @license + * Copyright 2022 The node-matter Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { WritableAttribute, Attribute, Cluster, Command, TlvNoArguments, TlvNoResponse } from "./Cluster"; +import { StatusCode } from "../interaction/InteractionMessages"; +import { TlvGroupId } from "../common/GroupId"; +import { BitFlag, MatterApplicationClusterSpecificationV1_0, TlvArray, TlvEnum, TlvField, TlvNullable, TlvObject, TlvString, TlvUInt16, TlvInt64 } from "@project-chip/matter.js"; +import { TlvEndpointNumber } from "../common/EndpointNumber"; + + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.1 */ +const TlvGroupKeyMapStruct = TlvObject({ + groupId: TlvField(0, TlvGroupId), /* min: 1 */ + groupKeySetId: TlvField(1, TlvUInt16), +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.2 */ +const TlvGroupKeySetStruct = TlvObject({ + groupKeySetID: TlvField(0, TlvUInt16), + groupKeySecurityPolicy: TlvField(1, TlvUInt16), + + epochKey0: TlvField(2, TlvNullable(TlvString.bound({ maxLength: 16 }))), + epochStartTime0: TlvField(3, TlvNullable(TlvInt64)), // epoch_us + + epochKey1: TlvField(4, TlvNullable(TlvString.bound({ maxLength: 16 }))), + epochStartTime1: TlvField(5, TlvNullable(TlvInt64)), // epoch_us + + epochKey2: TlvField(6, TlvNullable(TlvString.bound({ maxLength: 16 }))), + epochStartTime2: TlvField(7, TlvNullable(TlvInt64)), // epoch_us +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.3 */ +const TlvGroupInfoMapStruct = TlvObject({ + groupId: TlvField(1, TlvGroupId), /* min: 1 */ + endPoints: TlvField(2, TlvArray(TlvEndpointNumber)), + groupName: TlvField(3, TlvString.bound( { maxLength: 16 })), +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.2 table 87 */ +export const enum GroupKeySecurityPolicyEnum { + /** Message counter synchronization using trust-first */ + TrustFirst = 0x00, + + /** Message counter synchronization using cache-and-sync */ + CacheAndSync = 0x01, + } + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.1 */ +const TlvKeySetWriteRequest= TlvObject({ + groupKeySet: TlvField(0, TlvGroupKeySetStruct, ) +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.1 */ +const TlvKeySetWriteResponse= TlvObject({ + status: TlvField(0, TlvEnum()), +}); + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.2 */ +const TlvKeySetReadRequest= TlvObject({ + groupKeySetId: TlvField(0, TlvUInt16, ) +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.3 */ +const TlvKeySetReadResponse= TlvObject({ + groupKeySet: TlvField(0, TlvGroupKeySetStruct), +}); + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.4 */ +const TlvKeySetRemoveRequest= TlvObject({ + groupKeySetId: TlvField(0, TlvUInt16, ) +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.4 */ +const TlvKeySetRemoveResponse= TlvObject({ + status: TlvField(0, TlvEnum()), //TODO +}); + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.5 */ + const TlvKeySetReadAllIndicesRequest= TlvObject({ + // Spec says no payload which seems correct but chip XML shows the following + // groupKeySetIds: TlvField(0, TlvArray(TlvUInt16), ) +}); + +/** @see {@link MatterApplicationClusterSpecificationV1_0} §1 1.2.9.6 */ +const TlvKeySetReadAllIndicesResponse= TlvObject({ + groupKeySetIds: TlvField(0, TlvArray(TlvUInt16), ) +}); + +/** + * The Group Key Management Cluster is the mechanism by which group keys are managed. + * + * @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2 + */ +export const GroupKeyManagementCluster = Cluster({ + id: 0x3f, + name: "GroupKeyManagement", + revision: 1, + features: { + /** The ability to support CacheAndSync security policy and MCSP. */ + cacheAndSync: BitFlag(0), + }, + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.7.1 */ + attributes: { + /** Each entry associates a logical Group Id with a particular group key set. */ + groupKeyMap: WritableAttribute(0, TlvArray(TlvGroupKeyMapStruct, { maxLength: 254 })), + + /** Each entry provides read-only information about how a given logical Group ID maps to a particular set of endpoints */ + groupTable: Attribute(1, TlvArray(TlvGroupInfoMapStruct, { maxLength: 254 })), + + /** Maximum number of groups that this node supports per fabric */ + maxGroupsPerFabric: Attribute(2, TlvUInt16), + + /** Maximum number of group key sets this node supports per fabric */ + maxGroupKeysPerFabric: Attribute(3, TlvUInt16), + }, + + /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9 */ + commands: { + /** Set the state of a given Group Key Set,including atomically updating the state of all epoch keys */ + keySetWrite: Command(0, TlvKeySetWriteRequest, 0, TlvKeySetWriteResponse), + + /** Read the state of a given Group Key Set */ + keySetRead: Command(1, TlvKeySetReadRequest, 1, TlvKeySetReadResponse), + + /** Remove all state of a given Group Key Set */ + keySetRemove: Command(3, TlvKeySetRemoveRequest, 3, TlvKeySetRemoveResponse), + + /** Query a list of all Group Key Sets associated with the accessing fabric */ + keySetReadAllIndices: Command(5, TlvKeySetReadAllIndicesRequest, 5, TlvKeySetReadAllIndicesResponse), + } +}); From e83af7a891bc5e369899e5e13ba73b7d64a58107 Mon Sep 17 00:00:00 2001 From: Jim Buzbee Date: Fri, 10 Mar 2023 15:18:59 -0700 Subject: [PATCH 2/5] formatting --- src/matter/cluster/GroupKeyManagementCluster.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matter/cluster/GroupKeyManagementCluster.ts b/src/matter/cluster/GroupKeyManagementCluster.ts index 0f94adf..72d4501 100644 --- a/src/matter/cluster/GroupKeyManagementCluster.ts +++ b/src/matter/cluster/GroupKeyManagementCluster.ts @@ -79,7 +79,7 @@ const TlvKeySetRemoveResponse= TlvObject({ }); /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.5 */ - const TlvKeySetReadAllIndicesRequest= TlvObject({ +const TlvKeySetReadAllIndicesRequest= TlvObject({ // Spec says no payload which seems correct but chip XML shows the following // groupKeySetIds: TlvField(0, TlvArray(TlvUInt16), ) }); From 0fdf8b4b0785bfde2604db708c4f3ef38a017a9d Mon Sep 17 00:00:00 2001 From: Jim Buzbee Date: Sat, 11 Mar 2023 13:30:46 -0700 Subject: [PATCH 3/5] Address comments from last Pull Request. --- .../cluster/GroupKeyManagementCluster.ts | 101 +++++++++--------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/src/matter/cluster/GroupKeyManagementCluster.ts b/src/matter/cluster/GroupKeyManagementCluster.ts index 72d4501..6dfc4a6 100644 --- a/src/matter/cluster/GroupKeyManagementCluster.ts +++ b/src/matter/cluster/GroupKeyManagementCluster.ts @@ -7,39 +7,50 @@ import { WritableAttribute, Attribute, Cluster, Command, TlvNoArguments, TlvNoResponse } from "./Cluster"; import { StatusCode } from "../interaction/InteractionMessages"; import { TlvGroupId } from "../common/GroupId"; -import { BitFlag, MatterApplicationClusterSpecificationV1_0, TlvArray, TlvEnum, TlvField, TlvNullable, TlvObject, TlvString, TlvUInt16, TlvInt64 } from "@project-chip/matter.js"; +import { BitFlag, MatterCoreSpecificationV1_0, TlvArray, TlvEnum, TlvField, TlvNullable, TlvObject, TlvOptionalField, TlvString, TlvUInt16, TlvUInt64 } from "@project-chip/matter.js"; import { TlvEndpointNumber } from "../common/EndpointNumber"; -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.1 */ -const TlvGroupKeyMapStruct = TlvObject({ - groupId: TlvField(0, TlvGroupId), /* min: 1 */ - groupKeySetId: TlvField(1, TlvUInt16), +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.1 */ +const TlvGroupKeyMap = TlvObject({ + groupId: TlvField(1, TlvGroupId), /* min: 1 */ + groupKeySetId: TlvField(2, TlvUInt16), }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.2 */ -const TlvGroupKeySetStruct = TlvObject({ +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.2 */ +const TlvGroupKeySet = TlvObject({ groupKeySetID: TlvField(0, TlvUInt16), - groupKeySecurityPolicy: TlvField(1, TlvUInt16), + groupKeySecurityPolicy: TlvField(1, TlvEnum()), epochKey0: TlvField(2, TlvNullable(TlvString.bound({ maxLength: 16 }))), - epochStartTime0: TlvField(3, TlvNullable(TlvInt64)), // epoch_us + epochStartTime0: TlvField(3, TlvNullable(TlvUInt64)), // epoch_us epochKey1: TlvField(4, TlvNullable(TlvString.bound({ maxLength: 16 }))), - epochStartTime1: TlvField(5, TlvNullable(TlvInt64)), // epoch_us + epochStartTime1: TlvField(5, TlvNullable(TlvUInt64)), // epoch_us epochKey2: TlvField(6, TlvNullable(TlvString.bound({ maxLength: 16 }))), - epochStartTime2: TlvField(7, TlvNullable(TlvInt64)), // epoch_us + epochStartTime2: TlvField(7, TlvNullable(TlvUInt64)), // epoch_us + + GroupKeyMulticastPolicy: TlvOptionalField(8, TlvEnum()), }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.3 */ -const TlvGroupInfoMapStruct = TlvObject({ +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.3 */ +const TlvGroupInfoMap = TlvObject({ groupId: TlvField(1, TlvGroupId), /* min: 1 */ - endPoints: TlvField(2, TlvArray(TlvEndpointNumber)), - groupName: TlvField(3, TlvString.bound( { maxLength: 16 })), + endPoints: TlvField(2, TlvArray(TlvEndpointNumber, { minLength: 1 })), + groupName: TlvOptionalField(3, TlvString.bound( { maxLength: 16 })), }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.6.2 table 87 */ +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.6 table 88 */ +export const enum GroupKeyMulticastPolicyEnum { + /** The 16-bit Group Identifier of the MulticastAddress SHALL be the Group ID of the group. */ + PerGroupID = 0x00, + + /** The 16-bit Group Identifier of the Multicast Address SHALL be 0xFFFF */ + AllNodes = 0x01, + } + +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.2 table 87 */ export const enum GroupKeySecurityPolicyEnum { /** Message counter synchronization using trust-first */ TrustFirst = 0x00, @@ -48,51 +59,35 @@ export const enum GroupKeySecurityPolicyEnum { CacheAndSync = 0x01, } - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.1 */ + /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.1 */ const TlvKeySetWriteRequest= TlvObject({ - groupKeySet: TlvField(0, TlvGroupKeySetStruct, ) + groupKeySet: TlvField(0, TlvGroupKeySet) }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.1 */ -const TlvKeySetWriteResponse= TlvObject({ - status: TlvField(0, TlvEnum()), -}); - - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.2 */ + /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.2 */ const TlvKeySetReadRequest= TlvObject({ - groupKeySetId: TlvField(0, TlvUInt16, ) + groupKeySetId: TlvField(0, TlvUInt16) }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.3 */ +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.3 */ const TlvKeySetReadResponse= TlvObject({ - groupKeySet: TlvField(0, TlvGroupKeySetStruct), + groupKeySet: TlvField(0, TlvGroupKeySet), }); - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.4 */ + /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.4 */ const TlvKeySetRemoveRequest= TlvObject({ - groupKeySetId: TlvField(0, TlvUInt16, ) -}); - -/** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.4 */ -const TlvKeySetRemoveResponse= TlvObject({ - status: TlvField(0, TlvEnum()), //TODO -}); - - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9.5 */ -const TlvKeySetReadAllIndicesRequest= TlvObject({ - // Spec says no payload which seems correct but chip XML shows the following - // groupKeySetIds: TlvField(0, TlvArray(TlvUInt16), ) + groupKeySetId: TlvField(0, TlvUInt16) }); -/** @see {@link MatterApplicationClusterSpecificationV1_0} §1 1.2.9.6 */ +/** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.6 */ const TlvKeySetReadAllIndicesResponse= TlvObject({ - groupKeySetIds: TlvField(0, TlvArray(TlvUInt16), ) + groupKeySetIds: TlvField(0, TlvArray(TlvUInt16)) }); /** * The Group Key Management Cluster is the mechanism by which group keys are managed. * - * @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2 + * @see {@link MatterCoreSpecificationV1_0} § 11.2 */ export const GroupKeyManagementCluster = Cluster({ id: 0x3f, @@ -103,33 +98,33 @@ export const GroupKeyManagementCluster = Cluster({ cacheAndSync: BitFlag(0), }, - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.7.1 */ + /** @see {@link MatterCoreSpecificationV1_0} § 11.2.7.1 */ attributes: { /** Each entry associates a logical Group Id with a particular group key set. */ - groupKeyMap: WritableAttribute(0, TlvArray(TlvGroupKeyMapStruct, { maxLength: 254 })), + groupKeyMap: WritableAttribute(0, TlvArray(TlvGroupKeyMap, { maxLength: 254 }), { persistent: true }), /* fabricSensitive: true */ /** Each entry provides read-only information about how a given logical Group ID maps to a particular set of endpoints */ - groupTable: Attribute(1, TlvArray(TlvGroupInfoMapStruct, { maxLength: 254 })), + groupTable: Attribute(1, TlvArray(TlvGroupInfoMap, { maxLength: 254 })), /* fabricSensitive: true */ /** Maximum number of groups that this node supports per fabric */ - maxGroupsPerFabric: Attribute(2, TlvUInt16), + maxGroupsPerFabric: Attribute(2, TlvUInt16, { default: 0 }), /** Maximum number of group key sets this node supports per fabric */ - maxGroupKeysPerFabric: Attribute(3, TlvUInt16), + maxGroupKeysPerFabric: Attribute(3, TlvUInt16.bound({min: 1}),{ default: 1} ), }, - /** @see {@link MatterApplicationClusterSpecificationV1_0} § 11.2.9 */ + /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9 */ commands: { /** Set the state of a given Group Key Set,including atomically updating the state of all epoch keys */ - keySetWrite: Command(0, TlvKeySetWriteRequest, 0, TlvKeySetWriteResponse), + keySetWrite: Command(0, TlvKeySetWriteRequest, 0, TlvNoResponse), /* isFabricScoped: true */ /** Read the state of a given Group Key Set */ - keySetRead: Command(1, TlvKeySetReadRequest, 1, TlvKeySetReadResponse), + keySetRead: Command(1, TlvKeySetReadRequest,2, TlvKeySetReadResponse), /* isFabricScoped: true */ /** Remove all state of a given Group Key Set */ - keySetRemove: Command(3, TlvKeySetRemoveRequest, 3, TlvKeySetRemoveResponse), + keySetRemove: Command(3, TlvKeySetRemoveRequest, 3, TlvNoResponse), /* isFabricScoped: true */ /** Query a list of all Group Key Sets associated with the accessing fabric */ - keySetReadAllIndices: Command(5, TlvKeySetReadAllIndicesRequest, 5, TlvKeySetReadAllIndicesResponse), + keySetReadAllIndices: Command(5, TlvNoArguments, 4, TlvKeySetReadAllIndicesResponse), /* isFabricScoped: true */ } }); From 1517cc7c212c94eb016f41364f21828cf8ad9d35 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 11 Mar 2023 23:14:58 +0100 Subject: [PATCH 4/5] Update GroupKeyManagementCluster.ts --- src/matter/cluster/GroupKeyManagementCluster.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/matter/cluster/GroupKeyManagementCluster.ts b/src/matter/cluster/GroupKeyManagementCluster.ts index 6dfc4a6..3989421 100644 --- a/src/matter/cluster/GroupKeyManagementCluster.ts +++ b/src/matter/cluster/GroupKeyManagementCluster.ts @@ -31,7 +31,8 @@ const TlvGroupKeySet = TlvObject({ epochKey2: TlvField(6, TlvNullable(TlvString.bound({ maxLength: 16 }))), epochStartTime2: TlvField(7, TlvNullable(TlvUInt64)), // epoch_us - GroupKeyMulticastPolicy: TlvOptionalField(8, TlvEnum()), + /** Provisional Field, Correct default behavior is that implied by value PerGroupID. */ + GroupKeyMulticastPolicy: TlvField(8, TlvEnum()), }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.3 */ @@ -110,7 +111,7 @@ export const GroupKeyManagementCluster = Cluster({ maxGroupsPerFabric: Attribute(2, TlvUInt16, { default: 0 }), /** Maximum number of group key sets this node supports per fabric */ - maxGroupKeysPerFabric: Attribute(3, TlvUInt16.bound({min: 1}),{ default: 1} ), + maxGroupKeysPerFabric: Attribute(3, TlvUInt16.bound({ min: 1 }),{ default: 1} ), }, /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9 */ From c0f714061e038cc7356951ef8638cb5fa1df72f2 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 11 Mar 2023 23:19:52 +0100 Subject: [PATCH 5/5] Update GroupKeyManagementCluster.ts --- .../cluster/GroupKeyManagementCluster.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/matter/cluster/GroupKeyManagementCluster.ts b/src/matter/cluster/GroupKeyManagementCluster.ts index 3989421..6843b8a 100644 --- a/src/matter/cluster/GroupKeyManagementCluster.ts +++ b/src/matter/cluster/GroupKeyManagementCluster.ts @@ -20,7 +20,7 @@ const TlvGroupKeyMap = TlvObject({ /** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.2 */ const TlvGroupKeySet = TlvObject({ groupKeySetID: TlvField(0, TlvUInt16), - groupKeySecurityPolicy: TlvField(1, TlvEnum()), + groupKeySecurityPolicy: TlvField(1, TlvEnum()), epochKey0: TlvField(2, TlvNullable(TlvString.bound({ maxLength: 16 }))), epochStartTime0: TlvField(3, TlvNullable(TlvUInt64)), // epoch_us @@ -32,7 +32,7 @@ const TlvGroupKeySet = TlvObject({ epochStartTime2: TlvField(7, TlvNullable(TlvUInt64)), // epoch_us /** Provisional Field, Correct default behavior is that implied by value PerGroupID. */ - GroupKeyMulticastPolicy: TlvField(8, TlvEnum()), + GroupKeyMulticastPolicy: TlvField(8, TlvEnum()), }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.3 */ @@ -43,7 +43,7 @@ const TlvGroupInfoMap = TlvObject({ }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.6 table 88 */ -export const enum GroupKeyMulticastPolicyEnum { +export const enum GroupKeyMulticastPolicy { /** The 16-bit Group Identifier of the MulticastAddress SHALL be the Group ID of the group. */ PerGroupID = 0x00, @@ -52,7 +52,7 @@ export const enum GroupKeyMulticastPolicyEnum { } /** @see {@link MatterCoreSpecificationV1_0} § 11.2.6.2 table 87 */ -export const enum GroupKeySecurityPolicyEnum { +export const enum GroupKeySecurityPolicy { /** Message counter synchronization using trust-first */ TrustFirst = 0x00, @@ -61,27 +61,27 @@ export const enum GroupKeySecurityPolicyEnum { } /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.1 */ -const TlvKeySetWriteRequest= TlvObject({ +const TlvKeySetWriteRequest = TlvObject({ groupKeySet: TlvField(0, TlvGroupKeySet) }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.2 */ -const TlvKeySetReadRequest= TlvObject({ +const TlvKeySetReadRequest = TlvObject({ groupKeySetId: TlvField(0, TlvUInt16) }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.3 */ -const TlvKeySetReadResponse= TlvObject({ +const TlvKeySetReadResponse = TlvObject({ groupKeySet: TlvField(0, TlvGroupKeySet), }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.4 */ -const TlvKeySetRemoveRequest= TlvObject({ +const TlvKeySetRemoveRequest = TlvObject({ groupKeySetId: TlvField(0, TlvUInt16) }); /** @see {@link MatterCoreSpecificationV1_0} § 11.2.9.6 */ -const TlvKeySetReadAllIndicesResponse= TlvObject({ +const TlvKeySetReadAllIndicesResponse = TlvObject({ groupKeySetIds: TlvField(0, TlvArray(TlvUInt16)) });