diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 2aa8858ee733f6..dcf55d1ee8c7e0 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED #include "TraceHandlers.h" @@ -61,6 +62,19 @@ CHIP_ERROR CHIPCommand::Run() ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityBeta, kIdentityBetaFabricId, trustStore)); ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityGamma, kIdentityGammaFabricId, trustStore)); + // Initialize Group Data + ReturnLogErrorOnFailure(chip::GroupTesting::InitProvider()); + for (auto it = mCommissioners.begin(); it != mCommissioners.end(); it++) + { + chip::FabricInfo * fabric = it->second->GetFabricInfo(); + if ((nullptr != fabric) && (0 != it->first.compare(kIdentityNull))) + { + uint8_t compressed_fabric_id[sizeof(uint64_t)]; + chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id); + ReturnLogErrorOnFailure(fabric->GetCompressedId(compressed_fabric_id_span)); + ReturnLogErrorOnFailure(chip::GroupTesting::InitData(fabric->GetFabricIndex(), compressed_fabric_id_span)); + } + } chip::DeviceLayer::PlatformMgr().ScheduleWork(RunQueuedCommand, reinterpret_cast(this)); CHIP_ERROR err = StartWaiting(GetWaitDuration()); diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index aff74685d00c28..e6b98bc0662b40 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -25,7 +25,6 @@ #include #include -#include void Commands::Register(const char * clusterName, commands_list commandsList) { @@ -45,9 +44,6 @@ int Commands::Run(int argc, char ** argv) err = mStorage.Init(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Storage failure: %s", chip::ErrorStr(err))); - err = chip::GroupTesting::InitGroupData(); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Group Data failure: %s", chip::ErrorStr(err))); - chip::Logging::SetLogFilter(mStorage.GetLoggingLevel()); err = RunCommand(argc, argv); diff --git a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp index 731dbdc4ee95ed..ddc6891a526e9e 100644 --- a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp +++ b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -285,10 +286,19 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::DecodableType & commandData) { - auto fabric = commandObj->GetAccessingFabricIndex(); - auto * provider = GetGroupDataProvider(); + auto provider = GetGroupDataProvider(); + auto fabric = Server::GetInstance().GetFabricTable().FindFabricWithIndex(commandObj->GetAccessingFabricIndex()); - if (nullptr == provider) + if (nullptr == provider || nullptr == fabric) + { + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); + return true; + } + + uint8_t compressed_fabric_id_buffer[sizeof(uint64_t)]; + MutableByteSpan compressed_fabric_id(compressed_fabric_id_buffer); + CHIP_ERROR err = fabric->GetCompressedId(compressed_fabric_id); + if (CHIP_NO_ERROR != err) { emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE); return true; @@ -347,7 +357,7 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( } // Set KeySet - CHIP_ERROR err = provider->SetKeySet(fabric, keyset); + err = provider->SetKeySet(fabric->GetFabricIndex(), compressed_fabric_id, keyset); if (CHIP_NO_ERROR == err) { ChipLogDetail(Zcl, "GroupKeyManagementCluster: KeySetWrite OK"); diff --git a/src/app/tests/TestWriteInteraction.cpp b/src/app/tests/TestWriteInteraction.cpp index 12d3d7c00927d3..9c5827575f829e 100644 --- a/src/app/tests/TestWriteInteraction.cpp +++ b/src/app/tests/TestWriteInteraction.cpp @@ -479,7 +479,10 @@ int Test_Setup(void * inContext) VerifyOrReturnError(TestContext::InitializeAsync(inContext) == SUCCESS, FAILURE); - VerifyOrReturnError(CHIP_NO_ERROR == chip::GroupTesting::InitGroupData(), FAILURE); + constexpr chip::FabricIndex kFabricIndex1 = 1; + static const uint8_t kCompressedFabricId[] = { 0x29, 0x06, 0xC9, 0x08, 0xD1, 0x15, 0xD3, 0x62 }; + VerifyOrReturnError(CHIP_NO_ERROR == chip::GroupTesting::InitProvider(), FAILURE); + VerifyOrReturnError(CHIP_NO_ERROR == chip::GroupTesting::InitData(kFabricIndex1, chip::ByteSpan(kCompressedFabricId)), FAILURE); return SUCCESS; } diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index f70c24a7f56050..e4979b7b24e963 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -330,6 +330,8 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate, return CHIP_NO_ERROR; } + FabricInfo * GetFabricInfo() { return mFabricInfo; } + void ReleaseOperationalDevice(NodeId remoteDeviceId); OperationalCredentialsDelegate * GetOperationalCredentialsDelegate() { return mOperationalCredentialsDelegate; } diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index 3ade7091661b58..e7262fe8fbbf38 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -169,7 +169,7 @@ CHIP_ERROR FabricInfo::LoadFromStorage(FabricStorage * storage) // Computing it here will save computational overhead when it's accessed by other // parts of the code. SuccessOrExit(err = ExtractNodeIdFabricIdFromOpCert(ByteSpan(info->mNOCCert, nocCertLen), &nodeId, &mFabricId)); - SuccessOrExit(err = GetCompressedId(mFabricId, nodeId, &mOperationalId)); + SuccessOrExit(err = GeneratePeerId(mFabricId, nodeId, &mOperationalId)); SuccessOrExit(err = SetICACert(ByteSpan(info->mICACert, icaCertLen))); SuccessOrExit(err = SetNOCCert(ByteSpan(info->mNOCCert, nocCertLen))); @@ -182,7 +182,7 @@ CHIP_ERROR FabricInfo::LoadFromStorage(FabricStorage * storage) return err; } -CHIP_ERROR FabricInfo::GetCompressedId(FabricId fabricId, NodeId nodeId, PeerId * compressedPeerId) const +CHIP_ERROR FabricInfo::GeneratePeerId(FabricId fabricId, NodeId nodeId, PeerId * compressedPeerId) const { ReturnErrorCodeIf(compressedPeerId == nullptr, CHIP_ERROR_INVALID_ARGUMENT); uint8_t compressedFabricIdBuf[sizeof(uint64_t)]; @@ -333,7 +333,7 @@ CHIP_ERROR FabricInfo::VerifyCredentials(const ByteSpan & noc, const ByteSpan & } } - ReturnErrorOnFailure(GetCompressedId(fabricId, nodeId, &nocPeerId)); + ReturnErrorOnFailure(GeneratePeerId(fabricId, nodeId, &nocPeerId)); nocPubkey = P256PublicKey(certificates.GetLastCert()[0].mPublicKey); return CHIP_NO_ERROR; diff --git a/src/credentials/FabricTable.h b/src/credentials/FabricTable.h index b966f8e8a80973..9d5e83ae57cb2c 100644 --- a/src/credentials/FabricTable.h +++ b/src/credentials/FabricTable.h @@ -30,6 +30,7 @@ #if CHIP_CRYPTO_HSM #include #endif +#include #include #include #include @@ -154,6 +155,16 @@ class DLL_EXPORT FabricInfo FabricId GetFabricId() const { return mFabricId; } FabricIndex GetFabricIndex() const { return mFabric; } + + CompressedFabricId GetCompressedId() const { return mOperationalId.GetCompressedFabricId(); } + + CHIP_ERROR GetCompressedId(MutableByteSpan & compressedFabricId) const + { + ReturnErrorCodeIf(compressedFabricId.size() != sizeof(uint64_t), CHIP_ERROR_INVALID_ARGUMENT); + Encoding::BigEndian::Put64(compressedFabricId.data(), GetCompressedId()); + return CHIP_NO_ERROR; + } + uint16_t GetVendorId() const { return mVendorId; } void SetVendorId(uint16_t vendorId) { mVendorId = vendorId; } @@ -252,7 +263,7 @@ class DLL_EXPORT FabricInfo /* Generate a compressed peer ID (containing compressed fabric ID) using provided fabric ID, node ID and root public key of the fabric. The generated compressed ID is returned via compressedPeerId output parameter */ - CHIP_ERROR GetCompressedId(FabricId fabricId, NodeId nodeId, PeerId * compressedPeerId) const; + CHIP_ERROR GeneratePeerId(FabricId fabricId, NodeId nodeId, PeerId * compressedPeerId) const; friend class FabricTable; diff --git a/src/credentials/GroupDataProvider.h b/src/credentials/GroupDataProvider.h index 72c65359482af1..8ae5a80f947417 100644 --- a/src/credentials/GroupDataProvider.h +++ b/src/credentials/GroupDataProvider.h @@ -287,9 +287,9 @@ class GroupDataProvider // Key Sets // - virtual CHIP_ERROR SetKeySet(FabricIndex fabric_index, const KeySet & keys) = 0; - virtual CHIP_ERROR GetKeySet(FabricIndex fabric_index, KeysetId keyset_id, KeySet & keys) = 0; - virtual CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, KeysetId keyset_id) = 0; + virtual CHIP_ERROR SetKeySet(FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, const KeySet & keys) = 0; + virtual CHIP_ERROR GetKeySet(FabricIndex fabric_index, KeysetId keyset_id, KeySet & keys) = 0; + virtual CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, KeysetId keyset_id) = 0; /** * Creates an iterator that may be used to obtain the list of key sets associated with the given fabric. * In order to release the allocated memory, the Release() method must be called after the iteration is finished. diff --git a/src/credentials/GroupDataProviderImpl.cpp b/src/credentials/GroupDataProviderImpl.cpp index 48fdc388857be1..fb4c0cc173e880 100644 --- a/src/credentials/GroupDataProviderImpl.cpp +++ b/src/credentials/GroupDataProviderImpl.cpp @@ -1582,7 +1582,8 @@ void GroupDataProviderImpl::GroupKeyIteratorImpl::Release() constexpr size_t GroupDataProvider::EpochKey::kLengthBytes; -CHIP_ERROR GroupDataProviderImpl::SetKeySet(chip::FabricIndex fabric_index, const KeySet & in_keyset) +CHIP_ERROR GroupDataProviderImpl::SetKeySet(chip::FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, + const KeySet & in_keyset) { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); @@ -1609,7 +1610,7 @@ CHIP_ERROR GroupDataProviderImpl::SetKeySet(chip::FabricIndex fabric_index, cons { ByteSpan epoch_key(in_keyset.epoch_keys[i].key, Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); MutableByteSpan key_span(keyset.operational_keys[i].value); - ReturnErrorOnFailure(Crypto::DeriveGroupOperationalKey(epoch_key, key_span)); + ReturnErrorOnFailure(Crypto::DeriveGroupOperationalKey(epoch_key, compressed_fabric_id, key_span)); ReturnErrorOnFailure(Crypto::DeriveGroupSessionId(key_span, keyset.operational_keys[i].hash)); } if (found) diff --git a/src/credentials/GroupDataProviderImpl.h b/src/credentials/GroupDataProviderImpl.h index 34a9bcf64bd24b..bf294e1b050ff8 100644 --- a/src/credentials/GroupDataProviderImpl.h +++ b/src/credentials/GroupDataProviderImpl.h @@ -74,7 +74,7 @@ class GroupDataProviderImpl : public GroupDataProvider // Key Sets // - CHIP_ERROR SetKeySet(FabricIndex fabric_index, const KeySet & keys) override; + CHIP_ERROR SetKeySet(FabricIndex fabric_index, const ByteSpan & compressed_fabric_id, const KeySet & keys) override; CHIP_ERROR GetKeySet(FabricIndex fabric_index, chip::KeysetId keyset_id, KeySet & keys) override; CHIP_ERROR RemoveKeySet(FabricIndex fabric_index, chip::KeysetId keyset_id) override; KeySetIterator * IterateKeySets(FabricIndex fabric_index) override; diff --git a/src/credentials/tests/TestFabricTable.cpp b/src/credentials/tests/TestFabricTable.cpp index b2902edf54523e..54e5cea88a4166 100644 --- a/src/credentials/tests/TestFabricTable.cpp +++ b/src/credentials/tests/TestFabricTable.cpp @@ -56,19 +56,19 @@ void TestGetCompressedFabricID(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, fabricInfo.SetRootCert(ByteSpan(sTestRootCert)) == CHIP_NO_ERROR); PeerId compressedId; - NL_TEST_ASSERT(inSuite, fabricInfo.GetCompressedId(1234, 4321, &compressedId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, fabricInfo.GeneratePeerId(1234, 4321, &compressedId) == CHIP_NO_ERROR); // We are compairing with hard coded values here (which are generated manually when the test was written) // This is to ensure that the same value is generated on big endian and little endian platforms. - // If in this test any input to GetCompressedId() is changed, this value must be recomputed. + // If in this test any input to GeneratePeerId() is changed, this value must be recomputed. NL_TEST_ASSERT(inSuite, compressedId.GetCompressedFabricId() == 0x090F17C67be7b663); NL_TEST_ASSERT(inSuite, compressedId.GetNodeId() == 4321); - NL_TEST_ASSERT(inSuite, fabricInfo.GetCompressedId(0xabcd, 0xdeed, &compressedId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, fabricInfo.GeneratePeerId(0xabcd, 0xdeed, &compressedId) == CHIP_NO_ERROR); // We are compairing with hard coded values here (which are generated manually when the test was written) // This is to ensure that the same value is generated on big endian and little endian platforms - // If in this test any input to GetCompressedId() is changed, this value must be recomputed. + // If in this test any input to GeneratePeerId() is changed, this value must be recomputed. NL_TEST_ASSERT(inSuite, compressedId.GetCompressedFabricId() == 0xf3fecbcec485d5d7); NL_TEST_ASSERT(inSuite, compressedId.GetNodeId() == 0xdeed); } diff --git a/src/credentials/tests/TestGroupDataProvider.cpp b/src/credentials/tests/TestGroupDataProvider.cpp index 6639a16b0f33fe..43dbceacac0a4a 100644 --- a/src/credentials/tests/TestGroupDataProvider.cpp +++ b/src/credentials/tests/TestGroupDataProvider.cpp @@ -50,8 +50,12 @@ static const size_t kSize2 = strlen(kValue2) + 1; constexpr uint16_t kMaxGroupsPerFabric = 5; constexpr uint16_t kMaxGroupKeysPerFabric = 8; -constexpr chip::FabricIndex kFabric1 = 1; -constexpr chip::FabricIndex kFabric2 = 7; +constexpr chip::FabricIndex kFabric1 = 1; +constexpr chip::FabricIndex kFabric2 = 7; +static const uint8_t kFabricIdBuffer1[] = { 0x29, 0x06, 0xC9, 0x08, 0xD1, 0x15, 0xD3, 0x62 }; +static const uint8_t kFabricIdBuffer2[] = { 0x94, 0xb2, 0x68, 0x9a, 0x72, 0xb0, 0xc5, 0x1c }; +constexpr ByteSpan kCompressedFabricId1(kFabricIdBuffer1); +constexpr ByteSpan kCompressedFabricId2(kFabricIdBuffer2); constexpr chip::GroupId kGroup1 = kMinFabricGroupId; constexpr chip::GroupId kGroup2 = 0x2222; @@ -711,14 +715,14 @@ void TestKeySets(nlTestSuite * apSuite, void * apContext) // Add KeySets - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet0)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet3)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet3)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet0)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet3)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet3)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet1)); // Get KeySets @@ -804,13 +808,13 @@ void TestKeySetIterator(nlTestSuite * apSuite, void * apContext) // Add data to iterate - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet0)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet3)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet3)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet3)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet3)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet1)); // Iterate Fabric 1 @@ -921,12 +925,12 @@ void TestPerFabricData(nlTestSuite * apSuite, void * apContext) KeySet keyset; - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet0)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet0)); NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->GetKeySet(kFabric2, kKeysetId0, keyset)); NL_TEST_ASSERT(apSuite, CompareKeySets(keyset, kKeySet0)); @@ -1017,10 +1021,10 @@ void TestGroupDecryption(nlTestSuite * apSuite, void * apContext) NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->AddEndpoint(kFabric2, kGroup3, kEndpointId3)); NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->AddEndpoint(kFabric2, kGroup3, kEndpointId4)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet0)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kKeySet2)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet1)); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kKeySet3)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet0)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric1, kCompressedFabricId1, kKeySet2)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet1)); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetKeySet(kFabric2, kCompressedFabricId2, kKeySet3)); NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetGroupKeyAt(kFabric1, 0, kGroup1Keyset0)); NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == provider->SetGroupKeyAt(kFabric1, 1, kGroup1Keyset2)); diff --git a/src/crypto/CHIPCryptoPAL.cpp b/src/crypto/CHIPCryptoPAL.cpp index 6e29a8b8665df2..84f355f6c55af2 100644 --- a/src/crypto/CHIPCryptoPAL.cpp +++ b/src/crypto/CHIPCryptoPAL.cpp @@ -755,8 +755,7 @@ CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & rootPublicKe } /* Operational Group Key Group, Security Salt: "GroupKey v1.0" */ -static const uint8_t kGroupSecuritySalt[] = { 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30 }; -static const uint8_t kOperationalGroupKeySalt[0] = {}; +static const uint8_t kGroupSecuritySalt[] = { 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30 }; /* Group Key Derivation Function, Info: "GroupKeyHash" ” */ static const uint8_t kGroupKeyHashInfo[] = { 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x48, 0x61, 0x73, 0x68 }; @@ -769,13 +768,13 @@ static const uint8_t kGroupKeyHashSalt[0] = {}; Info = Group Security Salt, Length = CRYPTO_SYMMETRIC_KEY_LENGTH_BITS) */ -CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, MutableByteSpan & out_key) +CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id, MutableByteSpan & out_key) { VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == epoch_key.size(), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES <= out_key.size(), CHIP_ERROR_INVALID_ARGUMENT); Crypto::HKDF_sha crypto; - return crypto.HKDF_SHA256(epoch_key.data(), epoch_key.size(), kOperationalGroupKeySalt, sizeof(kOperationalGroupKeySalt), + return crypto.HKDF_SHA256(epoch_key.data(), epoch_key.size(), compressed_fabric_id.data(), compressed_fabric_id.size(), kGroupSecuritySalt, sizeof(kGroupSecuritySalt), out_key.data(), Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES); } diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index aeab2efa0de674..e7d8f8429e4bed 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -1482,7 +1482,7 @@ class SymmetricKeyContext The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length. * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid. **/ -CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, MutableByteSpan & out_key); +CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id, MutableByteSpan & out_key); /** * @brief Derives the Group Session ID from a given operational group key using diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index f34e18267210be..ad2bd75f91c84e 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -2158,35 +2158,39 @@ static void TestPID_x509Extraction(nlTestSuite * inSuite, void * inContext) } } +static const uint8_t kCompressedFabricId[] = { 0x29, 0x06, 0xC9, 0x08, 0xD1, 0x15, 0xD3, 0x62 }; + const uint8_t kEpochKeyBuffer1[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf }; const uint8_t kEpochKeyBuffer2[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf }; -const uint8_t kGroupOperationalKey1[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0x9d, 0xe1, 0x07, 0xde, 0x33, 0x11, - 0x2c, 0x52, 0x11, 0x0b, 0x7e, 0xc1, - 0x20, 0x9e, 0x6f, 0x0c }; -const uint8_t kGroupOperationalKey2[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0x7a, 0x33, 0xdb, 0x90, 0x5c, 0x7b, - 0x7e, 0x14, 0xa9, 0x20, 0xf8, 0x40, - 0xae, 0x48, 0xd3, 0xfe }; -const uint16_t kGroupSessionId1 = 0xbc66; -const uint16_t kGroupSessionId2 = 0x038d; +const uint8_t kGroupOperationalKey1[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0x1f, 0x19, 0xed, 0x3c, 0xef, 0x8a, + 0x21, 0x1b, 0xaf, 0x30, 0x6f, 0xae, + 0xee, 0xe7, 0xaa, 0xc6 }; +const uint8_t kGroupOperationalKey2[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0xaa, 0x97, 0x9a, 0x48, 0xbd, 0x8c, + 0xdf, 0x29, 0x3a, 0x07, 0x09, 0xb9, + 0xc1, 0xeb, 0x19, 0x30 }; +const uint16_t kGroupSessionId1 = 0x6c80; +const uint16_t kGroupSessionId2 = 0x0c48; static void TestGroup_OperationalKeyDerivation(nlTestSuite * inSuite, void * inContext) { uint8_t key_buffer[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 }; ByteSpan epoch_key(kEpochKeyBuffer1, sizeof(kEpochKeyBuffer1)); MutableByteSpan operational_key(key_buffer, sizeof(key_buffer)); + ByteSpan compressed_fabric_id(kCompressedFabricId); // Invalid Epoch Key - NL_TEST_ASSERT(inSuite, CHIP_ERROR_INVALID_ARGUMENT == DeriveGroupOperationalKey(ByteSpan(), operational_key)); + NL_TEST_ASSERT(inSuite, + CHIP_ERROR_INVALID_ARGUMENT == DeriveGroupOperationalKey(ByteSpan(), compressed_fabric_id, operational_key)); // Epoch Key 1 - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupOperationalKey(epoch_key, operational_key)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupOperationalKey(epoch_key, compressed_fabric_id, operational_key)); NL_TEST_ASSERT(inSuite, 0 == memcmp(operational_key.data(), kGroupOperationalKey1, sizeof(kGroupOperationalKey1))); // Epoch Key 2 epoch_key = ByteSpan(kEpochKeyBuffer2, sizeof(kEpochKeyBuffer2)); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupOperationalKey(epoch_key, operational_key)); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == DeriveGroupOperationalKey(epoch_key, compressed_fabric_id, operational_key)); NL_TEST_ASSERT(inSuite, 0 == memcmp(operational_key.data(), kGroupOperationalKey2, sizeof(kGroupOperationalKey2))); } diff --git a/src/lib/support/TestGroupData.h b/src/lib/support/TestGroupData.h index 94a14d8cc0dce4..78dc2288cf7172 100644 --- a/src/lib/support/TestGroupData.h +++ b/src/lib/support/TestGroupData.h @@ -29,11 +29,10 @@ constexpr uint16_t kMaxGroupKeysPerFabric = 8; static chip::TestPersistentStorageDelegate sDeviceStorage; static chip::Credentials::GroupDataProviderImpl sGroupsProvider(sDeviceStorage, kMaxGroupsPerFabric, kMaxGroupKeysPerFabric); -static const chip::FabricIndex kFabric1 = 1; -static const chip::GroupId kGroup1 = 0x0101; -static const chip::GroupId kGroup2 = 0x0102; -static const chip::KeysetId kKeySet1 = 0x01a1; -static const chip::KeysetId kKeySet2 = 0x01a2; +static const chip::GroupId kGroup1 = 0x0101; +static const chip::GroupId kGroup2 = 0x0102; +static const chip::KeysetId kKeySet1 = 0x01a1; +static const chip::KeysetId kKeySet2 = 0x01a2; } // namespace @@ -41,20 +40,24 @@ namespace chip { namespace GroupTesting { -CHIP_ERROR InitGroupData() +CHIP_ERROR InitProvider() { ReturnErrorOnFailure(sGroupsProvider.Init()); chip::Credentials::SetGroupDataProvider(&sGroupsProvider); + return CHIP_NO_ERROR; +} +CHIP_ERROR InitData(chip::FabricIndex fabric_index, const ByteSpan & compressed_fabric_id) +{ // Groups const chip::Credentials::GroupDataProvider::GroupInfo group1(kGroup1, "Group #1"); - ReturnErrorOnFailure(sGroupsProvider.SetGroupInfo(kFabric1, group1)); - ReturnErrorOnFailure(sGroupsProvider.AddEndpoint(kFabric1, group1.group_id, 1)); + ReturnErrorOnFailure(sGroupsProvider.SetGroupInfo(fabric_index, group1)); + ReturnErrorOnFailure(sGroupsProvider.AddEndpoint(fabric_index, group1.group_id, 1)); const chip::Credentials::GroupDataProvider::GroupInfo group2(kGroup2, "Group #2"); - ReturnErrorOnFailure(sGroupsProvider.SetGroupInfo(kFabric1, group2)); - ReturnErrorOnFailure(sGroupsProvider.AddEndpoint(kFabric1, group2.group_id, 0)); + ReturnErrorOnFailure(sGroupsProvider.SetGroupInfo(fabric_index, group2)); + ReturnErrorOnFailure(sGroupsProvider.AddEndpoint(fabric_index, group2.group_id, 0)); // Key Sets @@ -66,7 +69,7 @@ CHIP_ERROR InitGroupData() { 1110002, { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf } }, }; memcpy(keyset1.epoch_keys, epoch_keys1, sizeof(epoch_keys1)); - CHIP_ERROR err = sGroupsProvider.SetKeySet(kFabric1, keyset1); + CHIP_ERROR err = sGroupsProvider.SetKeySet(fabric_index, compressed_fabric_id, keyset1); ReturnErrorOnFailure(err); chip::Credentials::GroupDataProvider::KeySet keyset2(kKeySet2, @@ -77,11 +80,11 @@ CHIP_ERROR InitGroupData() { 2220002, { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff } }, }; memcpy(keyset2.epoch_keys, epoch_keys2, sizeof(epoch_keys2)); - err = sGroupsProvider.SetKeySet(kFabric1, keyset2); + err = sGroupsProvider.SetKeySet(fabric_index, compressed_fabric_id, keyset2); ReturnErrorOnFailure(err); - sGroupsProvider.SetGroupKeyAt(kFabric1, 0, chip::Credentials::GroupDataProvider::GroupKey(kGroup1, kKeySet1)); - sGroupsProvider.SetGroupKeyAt(kFabric1, 1, chip::Credentials::GroupDataProvider::GroupKey(kGroup2, kKeySet2)); + sGroupsProvider.SetGroupKeyAt(fabric_index, 0, chip::Credentials::GroupDataProvider::GroupKey(kGroup1, kKeySet1)); + sGroupsProvider.SetGroupKeyAt(fabric_index, 1, chip::Credentials::GroupDataProvider::GroupKey(kGroup2, kKeySet2)); return CHIP_NO_ERROR; }