Skip to content

Commit 1533431

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Fix KeySetWrite command payload validation. (#26726)
There are three fixes here: 1. Move the epoch key validity checks up front, since per spec those should happen before any internal state verification checks. 2. Add a check that the GroupKeySecurityPolicy in the keyset has a valid value for GroupKeySecurityPolicyEnum. 3. If we don't support MCSP, we should be failing out if the GroupKeySecurityPolicy is set to CacheAndSync. Fixes #26692
1 parent 2f269c5 commit 1533431

File tree

6 files changed

+754
-247
lines changed

6 files changed

+754
-247
lines changed

src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp

+47-16
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class GroupKeyManagementAttributeAccess : public AttributeAccessInterface
109109
// Register for the GroupKeyManagement cluster on all endpoints.
110110
GroupKeyManagementAttributeAccess() : AttributeAccessInterface(Optional<EndpointId>(0), GroupKeyManagement::Id) {}
111111

112+
// TODO: Once there is MCSP support, this may need to change.
113+
static constexpr bool IsMCSPSupported() { return false; }
114+
112115
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override
113116
{
114117
VerifyOrDie(aPath.mClusterId == GroupKeyManagement::Id);
@@ -117,8 +120,15 @@ class GroupKeyManagementAttributeAccess : public AttributeAccessInterface
117120
{
118121
case GroupKeyManagement::Attributes::ClusterRevision::Id:
119122
return ReadClusterRevision(aPath.mEndpointId, aEncoder);
120-
case Attributes::FeatureMap::Id:
121-
return aEncoder.Encode(static_cast<uint32_t>(0));
123+
case Attributes::FeatureMap::Id: {
124+
uint32_t features = 0;
125+
if (IsMCSPSupported())
126+
{
127+
// TODO: Once there is MCSP support, this will need to add the
128+
// right feature bit.
129+
}
130+
return aEncoder.Encode(features);
131+
}
122132
case GroupKeyManagement::Attributes::GroupKeyMap::Id:
123133
return ReadGroupKeyMap(aPath.mEndpointId, aEncoder);
124134
case GroupKeyManagement::Attributes::GroupTable::Id:
@@ -296,29 +306,32 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback(
296306
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
297307
const chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::DecodableType & commandData)
298308
{
299-
auto provider = GetGroupDataProvider();
300-
auto fabric = Server::GetInstance().GetFabricTable().FindFabricWithIndex(commandObj->GetAccessingFabricIndex());
301-
302-
if (nullptr == provider || nullptr == fabric)
309+
if (commandData.groupKeySet.epochKey0.IsNull() || commandData.groupKeySet.epochStartTime0.IsNull() ||
310+
commandData.groupKeySet.epochKey0.Value().empty() || (0 == commandData.groupKeySet.epochStartTime0.Value()))
303311
{
304-
commandObj->AddStatus(commandPath, Status::Failure);
312+
// If the EpochKey0 field is null or its associated EpochStartTime0 field is null,
313+
// then this command SHALL fail with an INVALID_COMMAND
314+
commandObj->AddStatus(commandPath, Status::InvalidCommand);
305315
return true;
306316
}
307317

308-
uint8_t compressed_fabric_id_buffer[sizeof(uint64_t)];
309-
MutableByteSpan compressed_fabric_id(compressed_fabric_id_buffer);
310-
CHIP_ERROR err = fabric->GetCompressedFabricIdBytes(compressed_fabric_id);
311-
if (CHIP_NO_ERROR != err)
318+
if (commandData.groupKeySet.groupKeySecurityPolicy == GroupKeySecurityPolicyEnum::kUnknownEnumValue)
312319
{
313-
commandObj->AddStatus(commandPath, Status::Failure);
320+
// If a client indicates an enumeration value to the server, that is not
321+
// supported by the server, because it is ... a new value unrecognized
322+
// by a legacy server, then the server SHALL generate a general
323+
// constraint error
324+
commandObj->AddStatus(commandPath, Status::ConstraintError);
314325
return true;
315326
}
316327

317-
if (commandData.groupKeySet.epochKey0.IsNull() || commandData.groupKeySet.epochStartTime0.IsNull() ||
318-
commandData.groupKeySet.epochKey0.Value().empty() || (0 == commandData.groupKeySet.epochStartTime0.Value()))
328+
if (!GroupKeyManagementAttributeAccess::IsMCSPSupported() &&
329+
commandData.groupKeySet.groupKeySecurityPolicy == GroupKeySecurityPolicyEnum::kCacheAndSync)
319330
{
320-
// If the EpochKey0 field is null or its associated EpochStartTime0 field is null,
321-
// then this command SHALL fail with an INVALID_COMMAND
331+
// When CacheAndSync is not supported in the FeatureMap of this cluster,
332+
// any action attempting to set CacheAndSync in the
333+
// GroupKeySecurityPolicy field SHALL fail with an INVALID_COMMAND
334+
// error.
322335
commandObj->AddStatus(commandPath, Status::InvalidCommand);
323336
return true;
324337
}
@@ -366,6 +379,24 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback(
366379
keyset.num_keys_used++;
367380
}
368381

382+
auto provider = GetGroupDataProvider();
383+
auto fabric = Server::GetInstance().GetFabricTable().FindFabricWithIndex(commandObj->GetAccessingFabricIndex());
384+
385+
if (nullptr == provider || nullptr == fabric)
386+
{
387+
commandObj->AddStatus(commandPath, Status::Failure);
388+
return true;
389+
}
390+
391+
uint8_t compressed_fabric_id_buffer[sizeof(uint64_t)];
392+
MutableByteSpan compressed_fabric_id(compressed_fabric_id_buffer);
393+
CHIP_ERROR err = fabric->GetCompressedFabricIdBytes(compressed_fabric_id);
394+
if (CHIP_NO_ERROR != err)
395+
{
396+
commandObj->AddStatus(commandPath, Status::Failure);
397+
return true;
398+
}
399+
369400
// Set KeySet
370401
err = provider->SetKeySet(fabric->GetFabricIndex(), compressed_fabric_id, keyset);
371402
if (CHIP_NO_ERROR == err)

src/app/tests/suites/TestGroupKeyManagementCluster.yaml

+87-4
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ tests:
9191
EpochStartTime2: 1110002,
9292
}
9393

94-
- label: "KeySet Write 2"
94+
- label: "KeySet Write 2 CacheAndSync"
9595
command: "KeySetWrite"
96+
PICS: GRPKEY.S.F00
9697
arguments:
9798
values:
9899
- name: "GroupKeySet"
@@ -108,9 +109,28 @@ tests:
108109
EpochStartTime2: 2110002,
109110
}
110111

111-
- label: "KeySet Write 3"
112+
- label: "KeySet Write 2 TrustFirst"
113+
command: "KeySetWrite"
114+
PICS: "!GRPKEY.S.F00"
115+
arguments:
116+
values:
117+
- name: "GroupKeySet"
118+
value:
119+
{
120+
GroupKeySetID: 0x01a2,
121+
GroupKeySecurityPolicy: 0,
122+
EpochKey0: "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
123+
EpochStartTime0: 2110000,
124+
EpochKey1: "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
125+
EpochStartTime1: 2110001,
126+
EpochKey2: "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
127+
EpochStartTime2: 2110002,
128+
}
129+
130+
- label: "KeySet Write 3 CacheAndSync"
112131
identity: "beta"
113132
command: "KeySetWrite"
133+
PICS: GRPKEY.S.F00
114134
arguments:
115135
values:
116136
- name: "GroupKeySet"
@@ -128,6 +148,27 @@ tests:
128148
EpochStartTime2: 2110002,
129149
}
130150

151+
- label: "KeySet Write 3 TrustFirst"
152+
identity: "beta"
153+
command: "KeySetWrite"
154+
PICS: "!GRPKEY.S.F00"
155+
arguments:
156+
values:
157+
- name: "GroupKeySet"
158+
value:
159+
{
160+
GroupKeySetID: 0x01a3,
161+
GroupKeySecurityPolicy: 0,
162+
EpochKey0:
163+
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
164+
EpochStartTime0: 2110000,
165+
EpochKey1: "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
166+
EpochStartTime1: 2110001,
167+
EpochKey2:
168+
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
169+
EpochStartTime2: 2110002,
170+
}
171+
131172
- label: "KeySet Read"
132173
command: "KeySetRead"
133174
arguments:
@@ -502,8 +543,9 @@ tests:
502543
response:
503544
error: NOT_FOUND
504545

505-
- label: "KeySet Read (not removed)"
546+
- label: "KeySet Read (not removed) CacheAndSync"
506547
command: "KeySetRead"
548+
PICS: GRPKEY.S.F00
507549
arguments:
508550
values:
509551
- name: "GroupKeySetID"
@@ -523,6 +565,28 @@ tests:
523565
EpochStartTime2: 2110002,
524566
}
525567

568+
- label: "KeySet Read (not removed) TrustFirst"
569+
command: "KeySetRead"
570+
PICS: GRPKEY.S.F00
571+
arguments:
572+
values:
573+
- name: "GroupKeySetID"
574+
value: 0x01a2
575+
response:
576+
values:
577+
- name: "GroupKeySet"
578+
value:
579+
{
580+
GroupKeySetID: 0x01a2,
581+
GroupKeySecurityPolicy: 0,
582+
EpochKey0: null,
583+
EpochStartTime0: 2110000,
584+
EpochKey1: null,
585+
EpochStartTime1: 2110001,
586+
EpochKey2: null,
587+
EpochStartTime2: 2110002,
588+
}
589+
526590
- label: "Remove Group 1"
527591
cluster: "Groups"
528592
endpoint: 1
@@ -608,8 +672,9 @@ tests:
608672
EpochStartTime2: 1110002,
609673
}
610674

611-
- label: "KeySet Write 2"
675+
- label: "KeySet Write 2 CacheAndSync"
612676
command: "KeySetWrite"
677+
PICS: GRPKEY.S.F00
613678
arguments:
614679
values:
615680
- name: "GroupKeySet"
@@ -625,6 +690,24 @@ tests:
625690
EpochStartTime2: 2110002,
626691
}
627692

693+
- label: "KeySet Write 2 TrustFirst"
694+
command: "KeySetWrite"
695+
PICS: "!GRPKEY.S.F00"
696+
arguments:
697+
values:
698+
- name: "GroupKeySet"
699+
value:
700+
{
701+
GroupKeySetID: 0x01a2,
702+
GroupKeySecurityPolicy: 0,
703+
EpochKey0: "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
704+
EpochStartTime0: 2110000,
705+
EpochKey1: "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
706+
EpochStartTime1: 2110001,
707+
EpochKey2: "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
708+
EpochStartTime2: 2110002,
709+
}
710+
628711
- label: "Map Group 1 and Group 2 to KeySet 1 and group 2 to KeySet 2"
629712
command: "writeAttribute"
630713
attribute: "GroupKeyMap"

src/app/tests/suites/certification/PICS.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -3616,6 +3616,14 @@ PICS:
36163616
client?"
36173617
id: GRPKEY.C
36183618

3619+
#
3620+
# server / features
3621+
#
3622+
- label:
3623+
"Does the DUT(Server) support Group Key Management CacheAndSync
3624+
feature?"
3625+
id: GRPKEY.S.F00
3626+
36193627
#
36203628
# client / attributes
36213629
#

src/app/tests/suites/certification/ci-pics-values

+5-2
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,12 @@ G.C.C03.Tx=0
580580
G.C.C04.Tx=0
581581
G.C.C05.Tx=0
582582

583-
GRPKEY.C=1
584-
GRPKEY.S.A0001=0
585583
GRPKEY.S=1
584+
# No support for the CacheAndSync feature so far
585+
GRPKEY.S.F00=0
586+
GRPKEY.S.A0001=0
587+
588+
GRPKEY.C=1
586589
GRPKEY.C.A0000=1
587590
GRPKEY.C.A0001=0
588591
GRPKEY.C.C00.Tx=1

0 commit comments

Comments
 (0)