Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / tests / TestSecureSessionMgr.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    All rights reserved.
5  *
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
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 /**
20  *    @file
21  *      This file implements unit tests for the SecureSessionMgr implementation.
22  */
23
24 #define CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API // Up here in case some other header
25                                               // includes SecureSessionMgr.h indirectly
26
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>
35
36 #include <nlbyteorder.h>
37 #include <nlunit-test.h>
38
39 #include <errno.h>
40
41 #undef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
42
43 namespace {
44
45 using namespace chip;
46 using namespace chip::Inet;
47 using namespace chip::Transport;
48
49 using TestContext = chip::Test::IOContext;
50
51 TestContext sContext;
52
53 const char PAYLOAD[]                = "Hello!";
54 constexpr NodeId kSourceNodeId      = 123654;
55 constexpr NodeId kDestinationNodeId = 111222333;
56
57 class LoopbackTransport : public Transport::Base
58 {
59 public:
60     /// Transports are required to have a constructor that takes exactly one argument
61     CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
62
63     CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
64     {
65         HandleMessageReceived(header, address, std::move(msgBuf));
66         return CHIP_NO_ERROR;
67     }
68
69     bool CanSendToPeer(const PeerAddress & address) override { return true; }
70 };
71
72 class OutgoingTransport : public Transport::Base
73 {
74 public:
75     /// Transports are required to have a constructor that takes exactly one argument
76     CHIP_ERROR Init(const char * unused) { return CHIP_NO_ERROR; }
77
78     CHIP_ERROR SendMessage(const PacketHeader & header, const PeerAddress & address, System::PacketBufferHandle msgBuf) override
79     {
80         System::PacketBufferHandle recvdMsg = msgBuf.CloneData();
81
82         ReturnErrorOnFailure(header.EncodeBeforeData(msgBuf));
83
84         HandleMessageReceived(header, address, std::move(recvdMsg));
85         return CHIP_NO_ERROR;
86     }
87
88     bool CanSendToPeer(const PeerAddress & address) override { return true; }
89 };
90
91 class TestSessMgrCallback : public SecureSessionMgrDelegate
92 {
93 public:
94     void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session,
95                            System::PacketBufferHandle msgBuf, SecureSessionMgr * mgr) override
96     {
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
100
101         size_t data_len = msgBuf->DataLength();
102
103         int compare = memcmp(msgBuf->Start(), PAYLOAD, data_len);
104         NL_TEST_ASSERT(mSuite, compare == 0);
105
106         ReceiveHandlerCallCount++;
107     }
108
109     void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override
110     {
111         if (NewConnectionHandlerCallCount == 0)
112             mRemoteToLocalSession = session;
113         if (NewConnectionHandlerCallCount == 1)
114             mLocalToRemoteSession = session;
115         NewConnectionHandlerCallCount++;
116     }
117     void OnConnectionExpired(SecureSessionHandle session, SecureSessionMgr * mgr) override {}
118
119     nlTestSuite * mSuite = nullptr;
120     SecureSessionHandle mRemoteToLocalSession;
121     SecureSessionHandle mLocalToRemoteSession;
122     int ReceiveHandlerCallCount       = 0;
123     int NewConnectionHandlerCallCount = 0;
124 };
125
126 TestSessMgrCallback callback;
127
128 void CheckSimpleInitTest(nlTestSuite * inSuite, void * inContext)
129 {
130     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
131
132     TransportMgr<LoopbackTransport> transportMgr;
133     SecureSessionMgr secureSessionMgr;
134     CHIP_ERROR err;
135
136     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
137
138     err = transportMgr.Init("LOOPBACK");
139     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
140
141     Transport::AdminPairingTable admins;
142     err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
143     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
144 }
145
146 void CheckMessageTest(nlTestSuite * inSuite, void * inContext)
147 {
148     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
149
150     uint16_t payload_len = sizeof(PAYLOAD);
151
152     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
153
154     chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
155     NL_TEST_ASSERT(inSuite, !buffer.IsNull());
156
157     IPAddress addr;
158     IPAddress::FromString("127.0.0.1", addr);
159     CHIP_ERROR err = CHIP_NO_ERROR;
160
161     TransportMgr<LoopbackTransport> transportMgr;
162     SecureSessionMgr secureSessionMgr;
163
164     err = transportMgr.Init("LOOPBACK");
165     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
166
167     Transport::AdminPairingTable admins;
168     err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
169     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
170
171     callback.mSuite = inSuite;
172
173     secureSessionMgr.SetDelegate(&callback);
174
175     Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
176
177     Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
178     NL_TEST_ASSERT(inSuite, admin != nullptr);
179
180     admin = admins.AssignAdminId(1, kDestinationNodeId);
181     NL_TEST_ASSERT(inSuite, admin != nullptr);
182
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);
186
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);
190
191     SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
192
193     // Should be able to send a message to itself by just calling send.
194     callback.ReceiveHandlerCallCount = 0;
195
196     err = secureSessionMgr.SendMessage(localToRemoteSession, std::move(buffer));
197     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
198
199     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
200
201     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
202 }
203
204 void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
205 {
206     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
207
208     uint16_t payload_len = sizeof(PAYLOAD);
209
210     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
211
212     chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
213     NL_TEST_ASSERT(inSuite, !buffer.IsNull());
214
215     IPAddress addr;
216     IPAddress::FromString("127.0.0.1", addr);
217     CHIP_ERROR err = CHIP_NO_ERROR;
218
219     TransportMgr<OutgoingTransport> transportMgr;
220     SecureSessionMgr secureSessionMgr;
221
222     err = transportMgr.Init("LOOPBACK");
223     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
224
225     Transport::AdminPairingTable admins;
226     err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
227     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
228
229     callback.mSuite = inSuite;
230
231     secureSessionMgr.SetDelegate(&callback);
232
233     Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
234
235     Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
236     NL_TEST_ASSERT(inSuite, admin != nullptr);
237
238     admin = admins.AssignAdminId(1, kDestinationNodeId);
239     NL_TEST_ASSERT(inSuite, admin != nullptr);
240
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);
244
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);
248
249     SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
250
251     // Should be able to send a message to itself by just calling send.
252     callback.ReceiveHandlerCallCount = 0;
253
254     PayloadHeader payloadHeader;
255     EncryptedPacketBufferHandle msgBuf;
256
257     // Set the exchange ID for this header.
258     payloadHeader.SetExchangeID(0);
259
260     // Set the protocol ID and message type for this header.
261     payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
262
263     payloadHeader.SetInitiator(true);
264
265     err = secureSessionMgr.SendMessage(localToRemoteSession, payloadHeader, std::move(buffer), &msgBuf);
266     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
267
268     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
269     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
270
271     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(msgBuf), nullptr);
272     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
273
274     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
275     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
276 }
277
278 void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext)
279 {
280     TestContext & ctx = *reinterpret_cast<TestContext *>(inContext);
281
282     uint16_t payload_len = sizeof(PAYLOAD);
283
284     ctx.GetInetLayer().SystemLayer()->Init(nullptr);
285
286     chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len);
287     NL_TEST_ASSERT(inSuite, !buffer.IsNull());
288
289     IPAddress addr;
290     IPAddress::FromString("127.0.0.1", addr);
291     CHIP_ERROR err = CHIP_NO_ERROR;
292
293     TransportMgr<OutgoingTransport> transportMgr;
294     SecureSessionMgr secureSessionMgr;
295
296     err = transportMgr.Init("LOOPBACK");
297     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
298
299     Transport::AdminPairingTable admins;
300     err = secureSessionMgr.Init(kSourceNodeId, ctx.GetInetLayer().SystemLayer(), &transportMgr, &admins);
301     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
302
303     callback.mSuite = inSuite;
304
305     secureSessionMgr.SetDelegate(&callback);
306
307     Optional<Transport::PeerAddress> peer(Transport::PeerAddress::UDP(addr, CHIP_PORT));
308
309     Transport::AdminPairingInfo * admin = admins.AssignAdminId(0, kSourceNodeId);
310     NL_TEST_ASSERT(inSuite, admin != nullptr);
311
312     admin = admins.AssignAdminId(1, kDestinationNodeId);
313     NL_TEST_ASSERT(inSuite, admin != nullptr);
314
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);
318
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);
322
323     SecureSessionHandle localToRemoteSession = callback.mLocalToRemoteSession;
324
325     // Should be able to send a message to itself by just calling send.
326     callback.ReceiveHandlerCallCount = 0;
327
328     PayloadHeader payloadHeader;
329     EncryptedPacketBufferHandle msgBuf;
330
331     // Set the exchange ID for this header.
332     payloadHeader.SetExchangeID(0);
333
334     // Set the protocol ID and message type for this header.
335     payloadHeader.SetMessageType(chip::Protocols::Echo::MsgType::EchoRequest);
336
337     payloadHeader.SetInitiator(true);
338
339     err = secureSessionMgr.SendMessage(localToRemoteSession, payloadHeader, std::move(buffer), &msgBuf);
340     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
341
342     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });
343     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
344
345     PacketHeader packetHeader;
346
347     // Change Destination Node ID
348     EncryptedPacketBufferHandle badDestNodeIdMsg = msgBuf.CloneData();
349     NL_TEST_ASSERT(inSuite, badDestNodeIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
350
351     NL_TEST_ASSERT(inSuite, packetHeader.GetDestinationNodeId().Value() == kDestinationNodeId);
352     packetHeader.SetDestinationNodeId(kSourceNodeId);
353     NL_TEST_ASSERT(inSuite, badDestNodeIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
354
355     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badDestNodeIdMsg), nullptr);
356     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
357
358     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
359
360     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
361
362     // Change Source Node ID
363     EncryptedPacketBufferHandle badSrcNodeIdMsg = msgBuf.CloneData();
364     NL_TEST_ASSERT(inSuite, badSrcNodeIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
365
366     packetHeader.SetSourceNodeId(kDestinationNodeId);
367     NL_TEST_ASSERT(inSuite, badSrcNodeIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
368
369     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badSrcNodeIdMsg), nullptr);
370     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
371
372     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
373
374     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
375
376     // Change Message ID
377     EncryptedPacketBufferHandle badMessageIdMsg = msgBuf.CloneData();
378     NL_TEST_ASSERT(inSuite, badMessageIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
379
380     uint32_t msgID = packetHeader.GetMessageId();
381     packetHeader.SetMessageId(msgID + 1);
382     NL_TEST_ASSERT(inSuite, badMessageIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR);
383
384     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badMessageIdMsg), nullptr);
385     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
386
387     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
388
389     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
390
391     // Change Key ID
392     EncryptedPacketBufferHandle badKeyIdMsg = msgBuf.CloneData();
393     NL_TEST_ASSERT(inSuite, badKeyIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR);
394
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);
398
399     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(badKeyIdMsg), nullptr);
400     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
401
402     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
403
404     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1);
405
406     // Send the correct encrypted msg
407     err = secureSessionMgr.SendEncryptedMessage(localToRemoteSession, std::move(msgBuf), nullptr);
408     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
409
410     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 1; });
411     NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2);
412 }
413
414 // Test Suite
415
416 /**
417  *  Test Suite that lists all the test functions.
418  */
419 // clang-format off
420 const nlTest sTests[] =
421 {
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),
426
427     NL_TEST_SENTINEL()
428 };
429 // clang-format on
430
431 int Initialize(void * aContext);
432 int Finalize(void * aContext);
433
434 // clang-format off
435 nlTestSuite sSuite =
436 {
437     "Test-CHIP-Connection",
438     &sTests[0],
439     Initialize,
440     Finalize
441 };
442 // clang-format on
443
444 /**
445  *  Initialize the test suite.
446  */
447 int Initialize(void * aContext)
448 {
449     CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Init(&sSuite);
450     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
451 }
452
453 /**
454  *  Finalize the test suite.
455  */
456 int Finalize(void * aContext)
457 {
458     CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
459     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
460 }
461
462 } // namespace
463
464 /**
465  *  Main
466  */
467 int TestSecureSessionMgr()
468 {
469     // Run test suit against one context
470     nlTestRunner(&sSuite, &sContext);
471
472     int r = (nlTestRunnerStats(&sSuite));
473     return r;
474 }
475
476 CHIP_REGISTER_TEST_SUITE(TestSecureSessionMgr);