3 * Copyright (c) 2020-2021 Project CHIP Authors
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements unit tests for the SecureSessionMgr implementation.
24 #define CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API // Up here in case some other header
25 // includes SecureSessionMgr.h indirectly
27 #include <core/CHIPCore.h>
28 #include <protocols/Protocols.h>
29 #include <protocols/echo/Echo.h>
30 #include <support/CodeUtils.h>
31 #include <support/UnitTestRegistration.h>
32 #include <transport/SecureSessionMgr.h>
33 #include <transport/TransportMgr.h>
34 #include <transport/raw/tests/NetworkTestHelpers.h>
36 #include <nlbyteorder.h>
37 #include <nlunit-test.h>
41 #undef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
46 using namespace chip::Inet;
47 using namespace chip::Transport;
49 using TestContext = chip::Test::IOContext;
53 const char PAYLOAD[] = "Hello!";
54 constexpr NodeId kSourceNodeId = 123654;
55 constexpr NodeId kDestinationNodeId = 111222333;
57 class LoopbackTransport : public Transport::Base
60 /// Transports are required to have a constructor that takes exactly one argument
61 CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
63 CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
65 HandleMessageReceived(header, address, std::move(msgBuf));
69 bool CanSendToPeer(const PeerAddress & address) override { return true; }
72 class OutgoingTransport : public Transport::Base
75 /// Transports are required to have a constructor that takes exactly one argument
76 CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
78 CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
80 System::PacketBufferHandle recvdMsg = msgBuf.CloneData();
82 ReturnErrorOnFailure(header.EncodeBeforeData(msgBuf));
84 HandleMessageReceived(header, address, std::move(recvdMsg));
88 bool CanSendToPeer(const PeerAddress & address) override { return true; }
91 class TestSessMgrCallback : public SecureSessionMgrDelegate
94 void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session,
95 System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override
97 NL_TEST_ASSERT(mSuite, header.GetSourceNodeId() == Optional<NodeId>::Value(kSourceNodeId));
98 NL_TEST_ASSERT(mSuite, header.GetDestinationNodeId() == Optional<NodeId>::Value(kDestinationNodeId));
99 NL_TEST_ASSERT(mSuite, session == mRemoteToLocalSession); // Packet received by remote peer
101 size_t data_len = msgBuf->DataLength();
103 int compare = memcmp(msgBuf->Start(), PAYLOAD, data_len);
104 NL_TEST_ASSERT(mSuite, compare == 0);
106 ReceiveHandlerCallCount++;
109 void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override
111 if (NewConnectionHandlerCallCount == 0)
112 mRemoteToLocalSession = session;
113 if (NewConnectionHandlerCallCount == 1)
114 mLocalToRemoteSession = session;
115 NewConnectionHandlerCallCount++;
117 void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override {}
119 nlTestSuite * mSuite = nullptr;
120 SecureSessionHandle mRemoteToLocalSession;
121 SecureSessionHandle mLocalToRemoteSession;
122 int ReceiveHandlerCallCount = 0;
123 int NewConnectionHandlerCallCount = 0;
126 TestSessMgrCallback callback;
128 void CheckSimpleInitTest(nlTestSuite * inSuite, void * inContext)
130 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
132 TransportMgr<LoopbackTransport> transportMgr;
133 SecureSessionMgr secureSessionMgr;
136 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
138 err = transportMgr.Init("LOOPBACK");
139 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
141 Transport::AdminPairingTable admins;
142 err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
143 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
146 void CheckMessageTest(nlTestSuite * inSuite, void * inContext)
148 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
150 uint16_t payload_len = sizeof(PAYLOAD);
152 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
154 chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
155 NL_TEST_ASSERT(inSuite, !buffer.IsNull());
158 IPAddress::FromString("127.0.0.1", addr);
159 CHIP_ERROR err = CHIP_NO_ERROR;
161 TransportMgr<LoopbackTransport> transportMgr;
162 SecureSessionMgr secureSessionMgr;
164 err = transportMgr.Init("LOOPBACK");
165 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
167 Transport::AdminPairingTable admins;
168 err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
169 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
171 callback.mSuite = inSuite;
173 secureSessionMgr.SetDelegate(&callback);
175 Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
177 Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
178 NL_TEST_ASSERT(inSuite, admin != nullptr);
180 admin = admins.AssignAdminId(1, kDestinationNodeId);
181 NL_TEST_ASSERT(inSuite, admin != nullptr);
183 SecurePairingUsingTestSecret pairing1(1, 2);
184 err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1, SecureSessionMgr::PairingDirection::kInitiator, 1);
185 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
187 SecurePairingUsingTestSecret pairing2(2, 1);
188 err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2, SecureSessionMgr::PairingDirection::kResponder, 0);
189 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
191 SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
193 // Should be able to send a message to itself by just calling send.
194 callback.ReceiveHandlerCallCount = 0;
196 err = secureSessionMgr.SendMessage(localToRemoteSession, std::move(buffer));
197 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
199 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
201 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
204 void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
206 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
208 uint16_t payload_len = sizeof(PAYLOAD);
210 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
212 chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
213 NL_TEST_ASSERT(inSuite, !buffer.IsNull());
216 IPAddress::FromString("127.0.0.1", addr);
217 CHIP_ERROR err = CHIP_NO_ERROR;
219 TransportMgr<OutgoingTransport> transportMgr;
220 SecureSessionMgr secureSessionMgr;
222 err = transportMgr.Init("LOOPBACK");
223 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
225 Transport::AdminPairingTable admins;
226 err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
227 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
229 callback.mSuite = inSuite;
231 secureSessionMgr.SetDelegate(&callback);
233 Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
235 Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
236 NL_TEST_ASSERT(inSuite, admin != nullptr);
238 admin = admins.AssignAdminId(1, kDestinationNodeId);
239 NL_TEST_ASSERT(inSuite, admin != nullptr);
241 SecurePairingUsingTestSecret pairing1(1, 2);
242 err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1, SecureSessionMgr::PairingDirection::kInitiator, 1);
243 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
245 SecurePairingUsingTestSecret pairing2(2, 1);
246 err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2, SecureSessionMgr::PairingDirection::kResponder, 0);
247 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
249 SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
251 // Should be able to send a message to itself by just calling send.
252 callback.ReceiveHandlerCallCount = 0;
254 PayloadHeader payloadHeader;
255 EncryptedPacketBufferHandle msgBuf;
257 // Set the exchange ID for this header.
258 payloadHeader.SetExchangeID(0);
260 // Set the protocol ID and message type for this header.
261 payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
263 payloadHeader.SetInitiator(true);
265 err = secureSessionMgr.SendMessage(localToRemoteSession, payloadHeader, std::move(buffer), &msgBuf);
266 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
268 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
269 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
271 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(msgBuf), nullptr);
272 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
274 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
275 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
278 void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
280 TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
282 uint16_t payload_len = sizeof(PAYLOAD);
284 ctx.GetInetLayer().SystemLayer()->Init(nullptr);
286 chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
287 NL_TEST_ASSERT(inSuite, !buffer.IsNull());
290 IPAddress::FromString("127.0.0.1", addr);
291 CHIP_ERROR err = CHIP_NO_ERROR;
293 TransportMgr<OutgoingTransport> transportMgr;
294 SecureSessionMgr secureSessionMgr;
296 err = transportMgr.Init("LOOPBACK");
297 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
299 Transport::AdminPairingTable admins;
300 err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
301 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
303 callback.mSuite = inSuite;
305 secureSessionMgr.SetDelegate(&callback);
307 Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
309 Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
310 NL_TEST_ASSERT(inSuite, admin != nullptr);
312 admin = admins.AssignAdminId(1, kDestinationNodeId);
313 NL_TEST_ASSERT(inSuite, admin != nullptr);
315 SecurePairingUsingTestSecret pairing1(1, 2);
316 err = secureSessionMgr.NewPairing(peer, kSourceNodeId, &pairing1, SecureSessionMgr::PairingDirection::kInitiator, 1);
317 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
319 SecurePairingUsingTestSecret pairing2(2, 1);
320 err = secureSessionMgr.NewPairing(peer, kDestinationNodeId, &pairing2, SecureSessionMgr::PairingDirection::kResponder, 0);
321 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
323 SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
325 // Should be able to send a message to itself by just calling send.
326 callback.ReceiveHandlerCallCount = 0;
328 PayloadHeader payloadHeader;
329 EncryptedPacketBufferHandle msgBuf;
331 // Set the exchange ID for this header.
332 payloadHeader.SetExchangeID(0);
334 // Set the protocol ID and message type for this header.
335 payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
337 payloadHeader.SetInitiator(true);
339 err = secureSessionMgr.SendMessage(localToRemoteSession, payloadHeader, std::move(buffer), &msgBuf);
340 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
342 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
343 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
345 PacketHeader packetHeader;
347 // Change Destination Node ID
348 EncryptedPacketBufferHandle badDestNodeIdMsg = msgBuf.CloneData();
349 NL_TEST_ASSERT(inSuite, badDestNodeIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
351 NL_TEST_ASSERT(inSuite, packetHeader.GetDestinationNodeId().Value() == kDestinationNodeId);
352 packetHeader.SetDestinationNodeId(kSourceNodeId);
353 NL_TEST_ASSERT(inSuite, badDestNodeIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
355 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badDestNodeIdMsg), nullptr);
356 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
358 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
360 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
362 // Change Source Node ID
363 EncryptedPacketBufferHandle badSrcNodeIdMsg = msgBuf.CloneData();
364 NL_TEST_ASSERT(inSuite, badSrcNodeIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
366 packetHeader.SetSourceNodeId(kDestinationNodeId);
367 NL_TEST_ASSERT(inSuite, badSrcNodeIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
369 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badSrcNodeIdMsg), nullptr);
370 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
372 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
374 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
377 EncryptedPacketBufferHandle badMessageIdMsg = msgBuf.CloneData();
378 NL_TEST_ASSERT(inSuite, badMessageIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
380 uint32_t msgID = packetHeader.GetMessageId();
381 packetHeader.SetMessageId(msgID + 1);
382 NL_TEST_ASSERT(inSuite, badMessageIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
384 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badMessageIdMsg), nullptr);
385 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
387 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
389 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
392 EncryptedPacketBufferHandle badKeyIdMsg = msgBuf.CloneData();
393 NL_TEST_ASSERT(inSuite, badKeyIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
395 // the secure channel is setup to use key ID 1, and 2. So let's use 3 here.
396 packetHeader.SetEncryptionKeyID(3);
397 NL_TEST_ASSERT(inSuite, badKeyIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
399 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badKeyIdMsg), nullptr);
400 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
402 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
404 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
406 // Send the correct encrypted msg
407 err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(msgBuf), nullptr);
408 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
410 ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
411 NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
417 * Test Suite that lists all the test functions.
420 const nlTest sTests[] =
422 NL_TEST_DEF("Simple Init Test", CheckSimpleInitTest),
423 NL_TEST_DEF("Message Self Test", CheckMessageTest),
424 NL_TEST_DEF("Send Encrypted Packet Test", SendEncryptedPacketTest),
425 NL_TEST_DEF("Send Bad Encrypted Packet Test", SendBadEncryptedPacketTest),
431 int Initialize(void * aContext);
432 int Finalize(void * aContext);
437 "Test-CHIP-Connection",
445 * Initialize the test suite.
447 int Initialize(void * aContext)
449 CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Init(&sSuite);
450 return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
454 * Finalize the test suite.
456 int Finalize(void * aContext)
458 CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
459 return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
467 int TestSecureSessionMgr()
469 // Run test suit against one context
470 nlTestRunner(&sSuite, &sContext);
472 int r = (nlTestRunnerStats(&sSuite));
476 CHIP_REGISTER_TEST_SUITE(TestSecureSessionMgr);