/* * * Copyright (c) 2020-2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file implements unit tests for the SessionManager implementation. */ #include #include #define CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API // Up here in case some other header // includes SessionManager.h indirectly #include #include #include #include #include #include #include #include #include #include #include #include #undef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API namespace { using namespace chip; using namespace chip::Inet; using namespace chip::Transport; using namespace chip::Test; using namespace chip::Credentials; using GroupInfo = GroupDataProvider::GroupInfo; using GroupKey = GroupDataProvider::GroupKey; using KeySet = GroupDataProvider::KeySet; using SecurityPolicy = GroupDataProvider::SecurityPolicy; using TestContext = chip::Test::LoopbackTransportManager; struct MessageTestEntry { const char * name; const char * peerAddr; const char * payload; const char * plain; const char * encrypted; const char * privacy; size_t payloadLength; size_t plainLength; size_t encryptedLength; size_t privacyLength; const char * encryptKey; const char * privacyKey; const char * epochKey; const char * nonce; const char * privacyNonce; const char * compressedFabricId; const char * mic; uint16_t sessionId; NodeId peerNodeId; GroupId groupId; NodeId sourceNodeId; uint8_t expectedMessageCount; }; struct MessageTestEntry theMessageTestVector[] = { // ======================================= // PASE positive test cases // ======================================= { .name = "secure pase message (no payload)", .peerAddr = "::1", .payload = "", .plain = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x05\x64\xee\x0e\x20\x7d", .encrypted = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d" "\x84\x7f\x53\x5c\x30\x07\xe6\x15\x0c\xd6\x58\x67\xf2\xb8\x17\xdb", // Includes MIC .privacy = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d" "\x84\x7f\x53\x5c\x30\x07\xe6\x15\x0c\xd6\x58\x67\xf2\xb8\x17\xdb", // Includes MIC .payloadLength = 0, .plainLength = 14, .encryptedLength = 30, .privacyLength = 30, // TODO(#22830): unicast message tests must use test key currently .encryptKey = "\x5e\xde\xd2\x44\xe5\x53\x2b\x3c\xdc\x23\x40\x9d\xba\xd0\x52\xd2", .nonce = "\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", .sessionId = 0x0bb8, // 3000 .peerNodeId = 0x0000000000000000ULL, .expectedMessageCount = 1, }, { .name = "secure pase message (short payload)", .peerAddr = "::1", .payload = "\x11\x22\x33\x44\x55", .plain = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x05\x64\xee\x0e\x20\x7d\x11\x22\x33\x44\x55", .encrypted = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d\x0f\x7f\x88\x5d\xfb" "\x2f\xaa\x89\x49\xcf\x73\x0a\x57\x28\xe0\x35\x46\x10\xa0\xc4\xa7", // Includes MIC .privacy = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d\x0f\x7f\x88\x5d\xfb" "\x2f\xaa\x89\x49\xcf\x73\x0a\x57\x28\xe0\x35\x46\x10\xa0\xc4\xa7", // Includes MIC .payloadLength = 5, .plainLength = 19, .encryptedLength = 35, .privacyLength = 35, // TODO(#22830): unicast message tests must use test key currently .encryptKey = "\x5e\xde\xd2\x44\xe5\x53\x2b\x3c\xdc\x23\x40\x9d\xba\xd0\x52\xd2", .nonce = "\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", .sessionId = 0x0bb8, // 3000 .peerNodeId = 0x0000000000000000ULL, .expectedMessageCount = 1, }, // ======================================= // PASE negative test cases // ======================================= { .name = "secure pase message (no payload / wrong MIC)", .peerAddr = "::1", .payload = "", .plain = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x05\x64\xee\x0e\x20\x7d", .encrypted = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d" "\x84\x7f\x53\x5c\x30\x07\xe6\x15\x0c\xd6\x58\x67\xf2\xb8\x17\xdd", // Includes wrong MIC .privacy = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d" "\x84\x7f\x53\x5c\x30\x07\xe6\x15\x0c\xd6\x58\x67\xf2\xb8\x17\xdd", // Includes wrong MIC .payloadLength = 0, .plainLength = 14, .encryptedLength = 30, .privacyLength = 30, // TODO(#22830): unicast message tests must use test key currently .encryptKey = "\x5e\xde\xd2\x44\xe5\x53\x2b\x3c\xdc\x23\x40\x9d\xba\xd0\x52\xd2", .nonce = "\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", .sessionId = 0x0bb8, // 3000 .peerNodeId = 0x0000000000000000ULL, .expectedMessageCount = 0, }, { .name = "secure pase message (short payload / wrong MIC)", .peerAddr = "::1", .payload = "\x11\x22\x33\x44\x55", .plain = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x05\x64\xee\x0e\x20\x7d\x11\x22\x33\x44\x55", .encrypted = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d\x0f\x7f\x88\x5d\xfb" "\x2f\xaa\x89\x49\xcf\x73\x0a\x57\x28\xe0\x35\x46\x10\xa0\xc4\xaa", // Includes wrong MIC .privacy = "\x00\xb8\x0b\x00\x39\x30\x00\x00\x5a\x98\x9a\xe4\x2e\x8d\x0f\x7f\x88\x5d\xfb" "\x2f\xaa\x89\x49\xcf\x73\x0a\x57\x28\xe0\x35\x46\x10\xa0\xc4\xaa", // Includes wrong MIC .payloadLength = 5, .plainLength = 19, .encryptedLength = 35, .privacyLength = 35, // TODO(#22830): unicast message tests must use test key currently .encryptKey = "\x5e\xde\xd2\x44\xe5\x53\x2b\x3c\xdc\x23\x40\x9d\xba\xd0\x52\xd2", .nonce = "\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", .sessionId = 0x0bb8, // 3000 .peerNodeId = 0x0000000000000000ULL, .expectedMessageCount = 0, }, { .name = "secure pase message (short payload / drop when privacy enabled)", .peerAddr = "::1", .payload = "\x11\x22\x33\x44\x55", .plain = "\x00\xb8\x0b\x80\x39\x30\x00\x00\x05\x64\xee\x0e\x20\x7d\x11\x22\x33\x44\x55", .encrypted = "\x00\xb8\x0b\x80\x39\x30\x00\x00\xaa\x26\xa0\xf9\x01\xef\xce\x9f\x9a\x67\xc8" "\x13\x79\x17\xd1\x5b\x81\xd1\x5d\x31\x33\x08\x31\x97\x58\xea\x3f", // Includes MIC .privacy = "\x00\xb8\x0b\x80\x87\xbe\xef\x06\xaa\x26\xa0\xf9\x01\xef\xce\x9f\x9a\x67\xc8" "\x13\x79\x17\xd1\x5b\x81\xd1\x5d\x31\x33\x08\x31\x97\x58\xea\x3f", // Includes MIC .payloadLength = 5, .plainLength = 19, .encryptedLength = 35, .privacyLength = 35, // TODO(#22830): unicast message tests must use test key currently .encryptKey = "\x5e\xde\xd2\x44\xe5\x53\x2b\x3c\xdc\x23\x40\x9d\xba\xd0\x52\xd2", .nonce = "\x80\x39\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\x0b\xb8\x81\xd1\x5d\x31\x33\x08\x31\x97\x58\xea\x3f", .sessionId = 0x0bb8, // 3000 .peerNodeId = 0x0000000000000000ULL, .expectedMessageCount = 0, }, #if !CHIP_CONFIG_SECURITY_TEST_MODE // ======================================= // GROUP positive test cases // ======================================= { .name = "secure group message (no privacy)", .peerAddr = "::1", .payload = "", // messageCounter = 0x12345678 // each group use case must increment this to pass replay. .plain = "\06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x64\xee\x0e\x20\x7d", .encrypted = "\x06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x65\xc7\x67\xbc\x6c\xda" "\x01\x06\xc9\x80\x13\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", // Includes MIC .privacy = "\x06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x65\xc7\x67\xbc\x6c\xda" "\x01\x06\xc9\x80\x13\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", // Includes MIC .payloadLength = 0, .plainLength = 24, .encryptedLength = 40, .privacyLength = 40, .encryptKey = "\xca\x92\xd7\xa0\x94\x2d\x1a\x51\x1a\x0e\x26\xad\x07\x4f\x4c\x2f", .privacyKey = "\xbf\xe9\xda\x01\x6a\x76\x53\x65\xf2\xdd\x97\xa9\xf9\x39\xe4\x25", .epochKey = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", .nonce = "\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\xdb\x7d\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", .sessionId = 0xdb7d, // 56189 .peerNodeId = 0x0000000000000000ULL, .groupId = 2, .sourceNodeId = 0x0000000000000002ULL, .expectedMessageCount = 1, }, { .name = "secure group message (no privacy, drop replay)", .peerAddr = "::1", .payload = "", // messageCounter = 0x12345678 // each group use case must increment this to pass replay. .plain = "\06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x64\xee\x0e\x20\x7d", .encrypted = "\x06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x65\xc7\x67\xbc\x6c\xda" "\x01\x06\xc9\x80\x13\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", // Includes MIC .privacy = "\x06\x7d\xdb\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x65\xc7\x67\xbc\x6c\xda" "\x01\x06\xc9\x80\x13\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", // Includes MIC .payloadLength = 0, .plainLength = 24, .encryptedLength = 40, .privacyLength = 40, .encryptKey = "\xca\x92\xd7\xa0\x94\x2d\x1a\x51\x1a\x0e\x26\xad\x07\x4f\x4c\x2f", .privacyKey = "\xbf\xe9\xda\x01\x6a\x76\x53\x65\xf2\xdd\x97\xa9\xf9\x39\xe4\x25", .epochKey = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", .nonce = "\x01\x78\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\xdb\x7d\x23\x90\x0e\x9b\x3c\xe6\xd4\xbb\x03\x27\xd6", .sessionId = 0xdb7d, // 56189 .peerNodeId = 0x0000000000000000ULL, .groupId = 2, .sourceNodeId = 0x0000000000000002ULL, .expectedMessageCount = 0, ///< same test vector as above, but drops due to replay protection }, { .name = "private group message", .peerAddr = "::1", .payload = "", // messageCounter = 0x12345679 .plain = "\x06\x7d\xdb\x81\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x64\xee\x0e\x20\x7d", .encrypted = "\x06\x7d\xdb\x81\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2b\x2f\x91\x5a\x66\xc9" "\x59\x62\x90\xeb\xe4\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xe1", .privacy = "\x06\x7d\xdb\x81\xd9\x26\xaf\xce\x24\xc8\xa0\x98\x1b\xdd\x44\xf4\xe7\x30\x2b\x2f\x91\x5a\x66\xc9" "\x59\x62\x90\xeb\xe4\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xe1", .payloadLength = 0, .plainLength = 24, .encryptedLength = 40, .privacyLength = 40, .encryptKey = "\xca\x92\xd7\xa0\x94\x2d\x1a\x51\x1a\x0e\x26\xad\x07\x4f\x4c\x2f", .privacyKey = "\xbf\xe9\xda\x01\x6a\x76\x53\x65\xf2\xdd\x97\xa9\xf9\x39\xe4\x25", .epochKey = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", .nonce = "\x01\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\xdb\x7d\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xe1", .sessionId = 0xdb7d, // 56189 .peerNodeId = 0x0000000000000000ULL, .groupId = 2, .sourceNodeId = 0x0000000000000002ULL, .expectedMessageCount = 1, }, // ======================================= // GROUP negative test cases // ======================================= { .name = "private group message (wrong MIC)", .peerAddr = "::1", .payload = "", // messageCounter = 0x12345679 .plain = "\x06\x7d\xdb\x81\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x64\xee\x0e\x20\x7d", .encrypted = "\x06\x7d\xdb\x81\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2b\x2f\x91\x5a\x66\xc9" "\x59\x62\x90\xeb\xe4\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xee", .privacy = "\x06\x7d\xdb\x81\xd9\x26\xaf\xce\x24\xc8\xa0\x98\x1b\xdd\x44\xf4\xe7\x30\x2b\x2f\x91\x5a\x66\xc9" "\x59\x62\x90\xeb\xe4\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xee", .payloadLength = 0, .plainLength = 24, .encryptedLength = 40, .privacyLength = 40, .encryptKey = "\xca\x92\xd7\xa0\x94\x2d\x1a\x51\x1a\x0e\x26\xad\x07\x4f\x4c\x2f", .privacyKey = "\xbf\xe9\xda\x01\x6a\x76\x53\x65\xf2\xdd\x97\xa9\xf9\x39\xe4\x25", .epochKey = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", .nonce = "\x01\x79\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\xdb\x7d\x40\x82\x17\xb3\xc0\xc9\x21\xa2\xfc\xa4\xe1", .sessionId = 0xdb7d, // 56189 .peerNodeId = 0x0000000000000000ULL, .groupId = 2, .sourceNodeId = 0x0000000000000002ULL, .expectedMessageCount = 0, }, #if CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2 // ======================================= // Test early-SVE2 workaround // ======================================= { .name = "secure group message (no privacy, but invalid P=1 flag)", .peerAddr = "::1", .payload = "", // messageCounter = 0x12345691 .plain = "\06\x7d\xdb\x81\x91\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x64\xee\x0e\x20\x7d", .encrypted = "\x06\x7d\xdb\x81\x91\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x91\xe0\x22\x85\xe0\x59\x07\xe0" "\xd8\x68\x0c\x79\xac\x6d\x64\x46\x90\x65\xb2\x6f\x90\x26", // Includes MIC .privacy = "\x06\x7d\xdb\x81\x91\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x91\xe0\x22\x85\xe0\x59\x07\xe0" "\xd8\x68\x0c\x79\xac\x6d\x64\x46\x90\x65\xb2\x6f\x90\x26", // Includes MIC .payloadLength = 0, .plainLength = 24, .encryptedLength = 40, .privacyLength = 40, .encryptKey = "\xca\x92\xd7\xa0\x94\x2d\x1a\x51\x1a\x0e\x26\xad\x07\x4f\x4c\x2f", .privacyKey = "\xbf\xe9\xda\x01\x6a\x76\x53\x65\xf2\xdd\x97\xa9\xf9\x39\xe4\x25", .epochKey = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", .nonce = "\x01\x91\x56\x34\x12\x01\x00\x00\x00\x00\x00\x00\x00", .privacyNonce = "\xdb\x7d\x79\xac\x6d\x64\x46\x90\x65\xb2\x6f\x90\x26", .sessionId = 0xdb7d, // 56189 .peerNodeId = 0x0000000000000000ULL, .groupId = 2, .sourceNodeId = 0x0000000000000002ULL, .expectedMessageCount = 1, }, #endif // CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2 #endif // !CHIP_CONFIG_SECURITY_TEST_MODE }; const uint16_t theMessageTestVectorLength = sizeof(theMessageTestVector) / sizeof(theMessageTestVector[0]); // Just enough init to replace a ton of boilerplate constexpr FabricIndex kFabricIndex = kMinValidFabricIndex; constexpr size_t kGroupIndex = 0; constexpr uint16_t kMaxGroupsPerFabric = 5; constexpr uint16_t kMaxGroupKeysPerFabric = 8; static chip::TestPersistentStorageDelegate sStorageDelegate; static chip::Crypto::DefaultSessionKeystore sSessionKeystore; static GroupDataProviderImpl sProvider(kMaxGroupsPerFabric, kMaxGroupKeysPerFabric); class FabricTableHolder { public: FabricTableHolder() {} ~FabricTableHolder() { mFabricTable.Shutdown(); mOpKeyStore.Finish(); mOpCertStore.Finish(); } CHIP_ERROR Init() { ReturnErrorOnFailure(mOpKeyStore.Init(&mStorage)); ReturnErrorOnFailure(mOpCertStore.Init(&mStorage)); // Initialize Group Data Provider sProvider.SetStorageDelegate(&sStorageDelegate); sProvider.SetSessionKeystore(&sSessionKeystore); // sProvider.SetListener(&chip::app::TestGroups::sListener); ReturnErrorOnFailure(sProvider.Init()); Credentials::SetGroupDataProvider(&sProvider); // Initialize Fabric Table chip::FabricTable::InitParams initParams; initParams.storage = &mStorage; initParams.operationalKeystore = &mOpKeyStore; initParams.opCertStore = &mOpCertStore; return mFabricTable.Init(initParams); } FabricTable & GetFabricTable() { return mFabricTable; } private: chip::FabricTable mFabricTable; chip::TestPersistentStorageDelegate mStorage; chip::PersistentStorageOperationalKeystore mOpKeyStore; chip::Credentials::PersistentStorageOpCertStore mOpCertStore; }; class TestSessionManagerCallback : public SessionMessageDelegate { public: void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, const SessionHandle & session, DuplicateMessage isDuplicate, System::PacketBufferHandle && msgBuf) override { mReceivedCount++; MessageTestEntry & testEntry = theMessageTestVector[mTestVectorIndex]; ChipLogProgress(Test, "OnMessageReceived: sessionId=0x%04x", testEntry.sessionId); EXPECT_EQ(header.GetSessionId(), testEntry.sessionId); size_t dataLength = msgBuf->DataLength(); size_t expectLength = testEntry.payloadLength; EXPECT_EQ(dataLength, expectLength); EXPECT_EQ(memcmp(msgBuf->Start(), testEntry.payload, dataLength), 0); ChipLogProgress(Test, "::: TestSessionManagerDispatch[%d] PASS", mTestVectorIndex); } void ResetTest(unsigned testVectorIndex) { mTestVectorIndex = testVectorIndex; mReceivedCount = 0; } unsigned NumMessagesReceived() { return mReceivedCount; } unsigned mTestVectorIndex = 0; unsigned mReceivedCount = 0; }; PeerAddress AddressFromString(const char * str) { Inet::IPAddress addr; VerifyOrDie(Inet::IPAddress::FromString(str, addr)); return PeerAddress::UDP(addr); } void TestSessionManagerInit(TestContext & ctx, SessionManager & sessionManager) { static FabricTableHolder fabricTableHolder; static secure_channel::MessageCounterManager gMessageCounterManager; static chip::TestPersistentStorageDelegate deviceStorage; static chip::Crypto::DefaultSessionKeystore sessionKeystore; EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); EXPECT_EQ(CHIP_NO_ERROR, sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, &fabricTableHolder.GetFabricTable(), sessionKeystore)); } // constexpr chip::FabricId kFabricId1 = 0x2906C908D115D362; static const uint8_t kCompressedFabricIdBuffer1[] = { 0x87, 0xe1, 0xb0, 0x04, 0xe2, 0x35, 0xa1, 0x30 }; constexpr ByteSpan kCompressedFabricId1(kCompressedFabricIdBuffer1); CHIP_ERROR InjectGroupSessionWithTestKey(SessionHolder & sessionHolder, MessageTestEntry & testEntry) { constexpr uint16_t kKeySetIndex = 0x0; GroupId groupId = testEntry.groupId; GroupDataProvider * provider = GetGroupDataProvider(); static KeySet sKeySet(kKeySetIndex, SecurityPolicy::kTrustFirst, 1); static GroupKey sGroupKeySet(groupId, kKeySetIndex); static GroupInfo sGroupInfo(groupId, "Name Matter Not"); static Transport::IncomingGroupSession sSessionBobToFriends(groupId, kFabricIndex, testEntry.sourceNodeId); if (testEntry.epochKey) { memcpy(sKeySet.epoch_keys[0].key, testEntry.epochKey, 16); sKeySet.epoch_keys[0].start_time = 0; sGroupInfo.group_id = groupId; sGroupKeySet.group_id = groupId; ReturnErrorOnFailure(provider->SetKeySet(kFabricIndex, kCompressedFabricId1, sKeySet)); ReturnErrorOnFailure(provider->SetGroupKeyAt(kFabricIndex, kGroupIndex, sGroupKeySet)); ReturnErrorOnFailure(provider->SetGroupInfoAt(kFabricIndex, kGroupIndex, sGroupInfo)); } sessionHolder = SessionHandle(sSessionBobToFriends); return CHIP_NO_ERROR; } class TestSessionManagerDispatch : public ::testing::Test { protected: void SetUp() { ASSERT_EQ(mContext.Init(), CHIP_NO_ERROR); } void TearDown() { mContext.Shutdown(); } TestContext mContext; }; TEST_F(TestSessionManagerDispatch, TestSessionManagerDispatch) { CHIP_ERROR err = CHIP_NO_ERROR; SessionManager sessionManager; TestSessionManagerCallback callback; TestSessionManagerInit(mContext, sessionManager); sessionManager.SetMessageDelegate(&callback); IPAddress addr; IPAddress::FromString("::1", addr); Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); SessionHolder aliceToBobSession; SessionHolder testGroupSession; for (unsigned i = 0; i < theMessageTestVectorLength; i++) { MessageTestEntry & testEntry = theMessageTestVector[i]; callback.ResetTest(i); ChipLogProgress(Test, "===> TestSessionManagerDispatch[%d] '%s': sessionId=0x%04x", i, testEntry.name, testEntry.sessionId); // TODO(#22830): inject raw keys rather than always defaulting to test key // TODO: switch on session type // Inject Sessions err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, testEntry.sessionId, testEntry.peerNodeId, testEntry.sessionId, kFabricIndex, peer, CryptoContext::SessionRole::kResponder); EXPECT_EQ(err, CHIP_NO_ERROR); err = InjectGroupSessionWithTestKey(testGroupSession, testEntry); EXPECT_EQ(CHIP_NO_ERROR, err); const char * plain = testEntry.plain; const ByteSpan expectedPlain(reinterpret_cast(plain), testEntry.plainLength); const char * privacy = testEntry.privacy; chip::System::PacketBufferHandle msg = chip::MessagePacketBuffer::NewWithData(reinterpret_cast(privacy), testEntry.privacyLength); const PeerAddress peerAddress = AddressFromString(testEntry.peerAddr); sessionManager.OnMessageReceived(peerAddress, std::move(msg)); EXPECT_EQ(callback.NumMessagesReceived(), testEntry.expectedMessageCount); if ((testEntry.expectedMessageCount == 0) && (callback.NumMessagesReceived() == 0)) { ChipLogProgress(Test, "::: TestSessionManagerDispatch[%d] PASS (negative test case)", i); } } sessionManager.Shutdown(); } } // namespace