blob: 12dc46ae360cc6dd5f8610445626a87ad4f5cde5 [file] [log] [blame]
/*
*
* 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.
*/
#define CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API // Up here in case some other header
// includes SessionManager.h indirectly
#include <credentials/PersistentStorageOpCertStore.h>
#include <credentials/tests/CHIPCert_unit_test_vectors.h>
#include <crypto/DefaultSessionKeystore.h>
#include <crypto/PersistentStorageOperationalKeystore.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/TestPersistentStorageDelegate.h>
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestRegistration.h>
#include <protocols/Protocols.h>
#include <protocols/echo/Echo.h>
#include <protocols/secure_channel/MessageCounterManager.h>
#include <protocols/secure_channel/PASESession.h>
#include <transport/SessionManager.h>
#include <transport/TransportMgr.h>
#include <transport/tests/LoopbackTransportManager.h>
#include <nlbyteorder.h>
#include <nlunit-test.h>
#include <errno.h>
#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::TestCerts;
using TestContext = chip::Test::LoopbackTransportManager;
const char PAYLOAD[] = "Hello!";
const char LARGE_PAYLOAD[kMaxAppMessageLen + 1] = "test message";
// Just enough init to replace a ton of boilerplate
class FabricTableHolder
{
public:
FabricTableHolder() {}
~FabricTableHolder()
{
mFabricTable.Shutdown();
mOpKeyStore.Finish();
mOpCertStore.Finish();
}
CHIP_ERROR Init()
{
ReturnErrorOnFailure(mOpKeyStore.Init(&mStorage));
ReturnErrorOnFailure(mOpCertStore.Init(&mStorage));
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 TestSessMgrCallback : public SessionMessageDelegate
{
public:
void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, const SessionHandle & session,
DuplicateMessage isDuplicate, System::PacketBufferHandle && msgBuf) override
{
size_t data_len = msgBuf->DataLength();
if (LargeMessageSent)
{
int compare = memcmp(msgBuf->Start(), LARGE_PAYLOAD, data_len);
NL_TEST_ASSERT(mSuite, compare == 0);
}
else
{
int compare = memcmp(msgBuf->Start(), PAYLOAD, data_len);
NL_TEST_ASSERT(mSuite, compare == 0);
}
ReceiveHandlerCallCount++;
}
nlTestSuite * mSuite = nullptr;
int ReceiveHandlerCallCount = 0;
bool LargeMessageSent = false;
};
void CheckSimpleInitTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
}
void CheckMessageTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
uint16_t payload_len = sizeof(PAYLOAD);
TestSessMgrCallback callback;
callback.LargeMessageSent = false;
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
callback.mSuite = inSuite;
sessionManager.SetMessageDelegate(&callback);
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Should be able to send a message to itself by just calling send.
callback.ReceiveHandlerCallCount = 0;
PayloadHeader payloadHeader;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
EncryptedPacketBufferHandle preparedMessage;
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
// Let's send the max sized message and make sure it is received
chip::System::PacketBufferHandle large_buffer = chip::MessagePacketBuffer::NewWithData(LARGE_PAYLOAD, kMaxAppMessageLen);
NL_TEST_ASSERT(inSuite, !large_buffer.IsNull());
callback.LargeMessageSent = true;
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(large_buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
uint16_t large_payload_len = sizeof(LARGE_PAYLOAD);
// Let's send bigger message than supported and make sure it fails to send
chip::System::PacketBufferHandle extra_large_buffer = chip::MessagePacketBuffer::NewWithData(LARGE_PAYLOAD, large_payload_len);
NL_TEST_ASSERT(inSuite, !extra_large_buffer.IsNull());
callback.LargeMessageSent = true;
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(extra_large_buffer),
preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_MESSAGE_TOO_LONG);
sessionManager.Shutdown();
}
void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
uint16_t payload_len = sizeof(PAYLOAD);
TestSessMgrCallback callback;
callback.LargeMessageSent = false;
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
callback.mSuite = inSuite;
sessionManager.SetMessageDelegate(&callback);
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Should be able to send a message to itself by just calling send.
callback.ReceiveHandlerCallCount = 0;
PayloadHeader payloadHeader;
EncryptedPacketBufferHandle preparedMessage;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
payloadHeader.SetInitiator(true);
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
// Reset receive side message counter, or duplicated message will be denied.
Transport::SecureSession * session = bobToAliceSession.Get().Value()->AsSecureSession();
session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
sessionManager.Shutdown();
}
void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
uint16_t payload_len = sizeof(PAYLOAD);
TestSessMgrCallback callback;
callback.LargeMessageSent = false;
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
callback.mSuite = inSuite;
sessionManager.SetMessageDelegate(&callback);
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Should be able to send a message to itself by just calling send.
callback.ReceiveHandlerCallCount = 0;
PayloadHeader payloadHeader;
EncryptedPacketBufferHandle preparedMessage;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
payloadHeader.SetInitiator(true);
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
/* -------------------------------------------------------------------------------------------*/
// Reset receive side message counter, or duplicated message will be denied.
Transport::SecureSession * session = bobToAliceSession.Get().Value()->AsSecureSession();
session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1);
PacketHeader packetHeader;
// Change Message ID
EncryptedPacketBufferHandle badMessageCounterMsg = preparedMessage.CloneData();
NL_TEST_ASSERT(inSuite, badMessageCounterMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
uint32_t messageCounter = packetHeader.GetMessageCounter();
packetHeader.SetMessageCounter(messageCounter + 1);
NL_TEST_ASSERT(inSuite, badMessageCounterMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), badMessageCounterMsg);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
/* -------------------------------------------------------------------------------------------*/
session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1);
// Change Key ID
EncryptedPacketBufferHandle badKeyIdMsg = preparedMessage.CloneData();
NL_TEST_ASSERT(inSuite, badKeyIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
// the secure channel is setup to use key ID 1, and 2. So let's use 3 here.
packetHeader.SetSessionId(3);
NL_TEST_ASSERT(inSuite, badKeyIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), badKeyIdMsg);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
/* -------------------------------------------------------------------------------------------*/
session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1);
// Send the correct encrypted msg
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
sessionManager.Shutdown();
}
void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
uint16_t payload_len = sizeof(PAYLOAD);
TestSessMgrCallback callback;
callback.LargeMessageSent = false;
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
callback.mSuite = inSuite;
sessionManager.SetMessageDelegate(&callback);
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
callback.ReceiveHandlerCallCount = 0;
PayloadHeader payloadHeader;
EncryptedPacketBufferHandle preparedMessage;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
payloadHeader.SetInitiator(true);
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
// Now advance our message counter by 5.
EncryptedPacketBufferHandle newMessage;
for (size_t i = 0; i < 5; ++i)
{
buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), newMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), newMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
// Now resend our original message. It should be rejected as a duplicate.
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
sessionManager.Shutdown();
}
void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
uint16_t payload_len = sizeof(PAYLOAD);
TestSessMgrCallback callback;
callback.LargeMessageSent = false;
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
callback.mSuite = inSuite;
sessionManager.SetMessageDelegate(&callback);
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
callback.ReceiveHandlerCallCount = 0;
PayloadHeader payloadHeader;
EncryptedPacketBufferHandle preparedMessage;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
payloadHeader.SetInitiator(true);
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
// Now advance our message counter by at least
// CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE + 2, so preparedMessage will be
// out of the window.
EncryptedPacketBufferHandle newMessage;
for (size_t i = 0; i < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE + 2; ++i)
{
buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), newMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
}
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), newMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
// Now resend our original message. It should be rejected as a duplicate.
err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
ctx.DrainAndServiceIO();
NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
sessionManager.Shutdown();
}
static void RandomSessionIdAllocatorOffset(nlTestSuite * inSuite, SessionManager & sessionManager, int max)
{
// Allocate + free a pseudo-random number of sessions to create a
// pseudo-random offset in mNextSessionId.
const int bound = rand() % max;
for (int i = 0; i < bound; ++i)
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
handle.Value()->AsSecureSession()->MarkForEviction();
}
}
void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
FabricTableHolder fabricTableHolder;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
secure_channel::MessageCounterManager messageCounterManager;
TestPersistentStorageDelegate deviceStorage1, deviceStorage2;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
SessionManager sessionManager;
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage1,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
// Allocate a session.
uint16_t sessionId1;
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
SessionHolder session;
session.GrabPairingSession(handle.Value());
sessionId1 = session->AsSecureSession()->GetLocalSessionId();
}
// Verify that we increment session ID by 1 for each allocation, except for
// the wraparound case where we skip session ID 0.
auto prevSessionId = sessionId1;
for (uint32_t i = 0; i < 10; ++i)
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
if (!handle.HasValue())
{
break;
}
auto sessionId = handle.Value()->AsSecureSession()->GetLocalSessionId();
NL_TEST_ASSERT(inSuite, sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535));
NL_TEST_ASSERT(inSuite, sessionId != 0);
prevSessionId = sessionId;
}
// Reconstruct the Session Manager to reset state.
sessionManager.Shutdown();
sessionManager.~SessionManager();
new (&sessionManager) SessionManager();
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage2,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
// Allocate a single session so we know what random id we are starting at.
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
prevSessionId = handle.Value()->AsSecureSession()->GetLocalSessionId();
handle.Value()->AsSecureSession()->MarkForEviction();
}
// Verify that we increment session ID by 1 for each allocation (except for
// the wraparound case where we skip session ID 0), even when allocated
// sessions are immediately freed.
for (uint32_t i = 0; i < UINT16_MAX + 10; ++i)
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
auto sessionId = handle.Value()->AsSecureSession()->GetLocalSessionId();
NL_TEST_ASSERT(inSuite, sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535));
NL_TEST_ASSERT(inSuite, sessionId != 0);
prevSessionId = sessionId;
handle.Value()->AsSecureSession()->MarkForEviction();
}
// Verify that the allocator does not give colliding IDs.
constexpr int collisionTestIterations = 1;
for (int i = 0; i < collisionTestIterations; ++i)
{
// Allocate some session handles at pseudo-random offsets in the session
// ID space.
constexpr size_t numHandles = CHIP_CONFIG_SECURE_SESSION_POOL_SIZE - 1;
Optional<SessionHandle> handles[numHandles];
uint16_t sessionIds[numHandles];
for (size_t h = 0; h < numHandles; ++h)
{
constexpr int maxOffset = 100;
handles[h] = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handles[h].HasValue());
sessionIds[h] = handles[h].Value()->AsSecureSession()->GetLocalSessionId();
RandomSessionIdAllocatorOffset(inSuite, sessionManager, maxOffset);
}
// Verify that none collide each other.
for (size_t h = 0; h < numHandles; ++h)
{
NL_TEST_ASSERT(inSuite, sessionIds[h] != sessionIds[(h + 1) % numHandles]);
}
// Allocate through the entire session ID space and verify that none of
// these collide either.
for (int j = 0; j < UINT16_MAX; ++j)
{
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
auto potentialCollision = handle.Value()->AsSecureSession()->GetLocalSessionId();
for (uint16_t sessionId : sessionIds)
{
NL_TEST_ASSERT(inSuite, potentialCollision != sessionId);
}
handle.Value()->AsSecureSession()->MarkForEviction();
}
// Free our allocated sessions.
for (auto & handle : handles)
{
handle.Value()->AsSecureSession()->MarkForEviction();
}
}
sessionManager.Shutdown();
}
void SessionCounterExhaustedTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
IPAddress addr;
IPAddress::FromString("::1", addr);
CHIP_ERROR err = CHIP_NO_ERROR;
FabricTableHolder fabricTableHolder;
SessionManager sessionManager;
secure_channel::MessageCounterManager gMessageCounterManager;
chip::TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
FabricIndex aliceFabricIndex = kUndefinedFabricIndex;
FabricIndex bobFabricIndex = kUndefinedFabricIndex;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
err =
fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert,
GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex);
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err);
SessionHolder aliceToBobSession;
err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2,
fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1,
aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder bobToAliceSession;
err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1,
fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2,
bobFabricIndex, peer, CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// ==== Set counter value to max ====
LocalSessionMessageCounter & counter = static_cast<LocalSessionMessageCounter &>(
aliceToBobSession.Get().Value()->AsSecureSession()->GetSessionMessageCounter().GetLocalMessageCounter());
counter.TestSetCounter(LocalSessionMessageCounter::kMessageCounterMax - 1);
// ==== Build a valid message with max counter value ====
chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD));
NL_TEST_ASSERT(inSuite, !buffer.IsNull());
PayloadHeader payloadHeader;
// Set the exchange ID for this header.
payloadHeader.SetExchangeID(0);
// Set the protocol ID and message type for this header.
payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
EncryptedPacketBufferHandle preparedMessage;
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// ==== Build another message which will fail becuase message counter is exhausted ====
chip::System::PacketBufferHandle buffer2 = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD));
NL_TEST_ASSERT(inSuite, !buffer2.IsNull());
EncryptedPacketBufferHandle preparedMessage2;
err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer2), preparedMessage2);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_MESSAGE_COUNTER_EXHAUSTED);
sessionManager.Shutdown();
}
static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
IPAddress addr;
IPAddress::FromString("::1", addr);
NodeId aliceNodeId = 0x11223344ull;
NodeId bobNodeId = 0x12344321ull;
FabricIndex aliceFabricIndex = 1;
FabricIndex bobFabricIndex = 1;
FabricTableHolder fabricTableHolder;
secure_channel::MessageCounterManager messageCounterManager;
TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
SessionManager sessionManager;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
SessionHolder aliceToBobSession;
CHIP_ERROR err = sessionManager.InjectCaseSessionWithTestKey(aliceToBobSession, 2, 1, aliceNodeId, bobNodeId, aliceFabricIndex,
peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
class StickySessionDelegate : public SessionDelegate
{
public:
NewSessionHandlingPolicy GetNewSessionHandlingPolicy() override { return NewSessionHandlingPolicy::kStayAtOldSession; }
void OnSessionReleased() override {}
} delegate;
SessionHolderWithDelegate stickyAliceToBobSession(aliceToBobSession.Get().Value(), delegate);
NL_TEST_ASSERT(inSuite, aliceToBobSession.Contains(stickyAliceToBobSession.Get().Value()));
SessionHolder bobToAliceSession;
err = sessionManager.InjectCaseSessionWithTestKey(bobToAliceSession, 1, 2, bobNodeId, aliceNodeId, bobFabricIndex, peer,
CryptoContext::SessionRole::kResponder);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
SessionHolder newAliceToBobSession;
err = sessionManager.InjectCaseSessionWithTestKey(newAliceToBobSession, 3, 4, aliceNodeId, bobNodeId, aliceFabricIndex, peer,
CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
// Here we got 3 sessions, and 4 holders:
// 1. alice -> bob: aliceToBobSession, stickyAliceToBobSession
// 2. alice <- bob: bobToAliceSession
// 3. alice -> bob: newAliceToBobSession
SecureSession * session1 = aliceToBobSession->AsSecureSession();
SecureSession * session2 = bobToAliceSession->AsSecureSession();
SecureSession * session3 = newAliceToBobSession->AsSecureSession();
NL_TEST_ASSERT(inSuite, session1 != session3);
NL_TEST_ASSERT(inSuite, stickyAliceToBobSession->AsSecureSession() == session1);
// Now shift the 1st session to the 3rd one, after shifting, holders should be:
// 1. alice -> bob: stickyAliceToBobSession
// 2. alice <- bob: bobToAliceSession
// 3. alice -> bob: aliceToBobSession, newAliceToBobSession
sessionManager.GetSecureSessions().NewerSessionAvailable(newAliceToBobSession.Get().Value()->AsSecureSession());
NL_TEST_ASSERT(inSuite, aliceToBobSession);
NL_TEST_ASSERT(inSuite, stickyAliceToBobSession);
NL_TEST_ASSERT(inSuite, newAliceToBobSession);
NL_TEST_ASSERT(inSuite, stickyAliceToBobSession->AsSecureSession() == session1);
NL_TEST_ASSERT(inSuite, bobToAliceSession->AsSecureSession() == session2);
NL_TEST_ASSERT(inSuite, aliceToBobSession->AsSecureSession() == session3);
NL_TEST_ASSERT(inSuite, newAliceToBobSession->AsSecureSession() == session3);
sessionManager.Shutdown();
}
static void TestFindSecureSessionForNode(nlTestSuite * inSuite, void * inContext)
{
TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
IPAddress addr;
IPAddress::FromString("::1", addr);
NodeId aliceNodeId = 0x11223344ull;
NodeId bobNodeId = 0x12344321ull;
FabricIndex aliceFabricIndex = 1;
FabricTableHolder fabricTableHolder;
secure_channel::MessageCounterManager messageCounterManager;
TestPersistentStorageDelegate deviceStorage;
chip::Crypto::DefaultSessionKeystore sessionKeystore;
SessionManager sessionManager;
NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init());
NL_TEST_ASSERT(inSuite,
CHIP_NO_ERROR ==
sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage,
&fabricTableHolder.GetFabricTable(), sessionKeystore));
Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
SessionHolder aliceToBobSession;
CHIP_ERROR err = sessionManager.InjectCaseSessionWithTestKey(aliceToBobSession, 2, 1, aliceNodeId, bobNodeId, aliceFabricIndex,
peer, CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
aliceToBobSession->AsSecureSession()->MarkActive();
SessionHolder newAliceToBobSession;
err = sessionManager.InjectCaseSessionWithTestKey(newAliceToBobSession, 3, 4, aliceNodeId, bobNodeId, aliceFabricIndex, peer,
CryptoContext::SessionRole::kInitiator);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
while (System::SystemClock().GetMonotonicTimestamp() <= aliceToBobSession->AsSecureSession()->GetLastActivityTime())
{
// Wait for the clock to advance so the new session is
// more-recently-active.
}
newAliceToBobSession->AsSecureSession()->MarkActive();
auto foundSession = sessionManager.FindSecureSessionForNode(ScopedNodeId(bobNodeId, aliceFabricIndex),
MakeOptional(SecureSession::Type::kCASE));
NL_TEST_ASSERT(inSuite, foundSession.HasValue());
NL_TEST_ASSERT(inSuite, newAliceToBobSession.Contains(foundSession.Value()));
NL_TEST_ASSERT(inSuite, !aliceToBobSession.Contains(foundSession.Value()));
sessionManager.Shutdown();
}
// Test Suite
/**
* Test Suite that lists all the test functions.
*/
// clang-format off
const nlTest sTests[] =
{
NL_TEST_DEF("Simple Init Test", CheckSimpleInitTest),
NL_TEST_DEF("Message Self Test", CheckMessageTest),
NL_TEST_DEF("Send Encrypted Packet Test", SendEncryptedPacketTest),
NL_TEST_DEF("Send Bad Encrypted Packet Test", SendBadEncryptedPacketTest),
NL_TEST_DEF("Old counter Test", SendPacketWithOldCounterTest),
NL_TEST_DEF("Too-old counter Test", SendPacketWithTooOldCounterTest),
NL_TEST_DEF("Session Allocation Test", SessionAllocationTest),
NL_TEST_DEF("Session Counter Exhausted Test", SessionCounterExhaustedTest),
NL_TEST_DEF("SessionShiftingTest", SessionShiftingTest),
NL_TEST_DEF("TestFindSecureSessionForNode", TestFindSecureSessionForNode),
NL_TEST_SENTINEL()
};
// clang-format on
int Initialize(void * aContext);
int Finalize(void * aContext);
// clang-format off
nlTestSuite sSuite =
{
"Test-CHIP-SessionManager",
&sTests[0],
Initialize,
Finalize
};
// clang-format on
/**
* Initialize the test suite.
*/
int Initialize(void * aContext)
{
CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Init();
return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
}
/**
* Finalize the test suite.
*/
int Finalize(void * aContext)
{
reinterpret_cast<TestContext *>(aContext)->Shutdown();
return SUCCESS;
}
} // namespace
/**
* Main
*/
int TestSessionManager()
{
return chip::ExecuteTestsWithContext<TestContext>(&sSuite);
}
CHIP_REGISTER_TEST_SUITE(TestSessionManager);