Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / tests / TestPASESession.cpp
1 /*
2  *
3  *    Copyright (c) 2020 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 PASESession implementation.
22  */
23
24 #include <errno.h>
25 #include <nlunit-test.h>
26
27 #include <core/CHIPCore.h>
28 #include <core/CHIPSafeCasts.h>
29 #include <stdarg.h>
30 #include <support/CHIPMem.h>
31 #include <support/CodeUtils.h>
32 #include <support/UnitTestRegistration.h>
33 #include <transport/PASESession.h>
34
35 using namespace chip;
36
37 class TestSecurePairingDelegate : public SessionEstablishmentDelegate
38 {
39 public:
40     CHIP_ERROR SendSessionEstablishmentMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress,
41                                                System::PacketBufferHandle msgBuf) override
42     {
43         mNumMessageSend++;
44         return (peer != nullptr) ? peer->HandlePeerMessage(header, peerAddress, std::move(msgBuf)) : mMessageSendError;
45     }
46
47     void OnSessionEstablishmentError(CHIP_ERROR error) override { mNumPairingErrors++; }
48
49     void OnSessionEstablished() override { mNumPairingComplete++; }
50
51     uint32_t mNumMessageSend     = 0;
52     uint32_t mNumPairingErrors   = 0;
53     uint32_t mNumPairingComplete = 0;
54     CHIP_ERROR mMessageSendError = CHIP_NO_ERROR;
55
56     PASESession * peer = nullptr;
57 };
58
59 void SecurePairingWaitTest(nlTestSuite * inSuite, void * inContext)
60 {
61     // Test all combinations of invalid parameters
62     TestSecurePairingDelegate delegate;
63     PASESession pairing;
64
65     NL_TEST_ASSERT(inSuite, pairing.WaitForPairing(1234, 500, nullptr, 0, 0, &delegate) == CHIP_ERROR_INVALID_ARGUMENT);
66     NL_TEST_ASSERT(inSuite,
67                    pairing.WaitForPairing(1234, 500, (const uint8_t *) "saltSalt", 8, 0, nullptr) == CHIP_ERROR_INVALID_ARGUMENT);
68     NL_TEST_ASSERT(inSuite, pairing.WaitForPairing(1234, 500, (const uint8_t *) "saltSalt", 8, 0, &delegate) == CHIP_NO_ERROR);
69 }
70
71 void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext)
72 {
73     // Test all combinations of invalid parameters
74     TestSecurePairingDelegate delegate;
75     PASESession pairing;
76
77     NL_TEST_ASSERT(inSuite, pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, nullptr) != CHIP_NO_ERROR);
78     NL_TEST_ASSERT(inSuite, pairing.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, &delegate) == CHIP_NO_ERROR);
79
80     NL_TEST_ASSERT(inSuite, delegate.mNumMessageSend == 1);
81
82     delegate.mMessageSendError = CHIP_ERROR_BAD_REQUEST;
83
84     PASESession pairing1;
85
86     NL_TEST_ASSERT(inSuite,
87                    pairing1.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, &delegate) == CHIP_ERROR_BAD_REQUEST);
88 }
89
90 void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, PASESession & pairingCommissioner,
91                                       TestSecurePairingDelegate & delegateCommissioner)
92 {
93     // Test all combinations of invalid parameters
94     TestSecurePairingDelegate delegateAccessory;
95     PASESession pairingAccessory;
96
97     delegateCommissioner.peer = &pairingAccessory;
98     delegateAccessory.peer    = &pairingCommissioner;
99
100     NL_TEST_ASSERT(inSuite,
101                    pairingAccessory.WaitForPairing(1234, 500, (const uint8_t *) "saltSALT", 8, 0, &delegateAccessory) ==
102                        CHIP_NO_ERROR);
103     NL_TEST_ASSERT(inSuite,
104                    pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, &delegateCommissioner) ==
105                        CHIP_NO_ERROR);
106
107     NL_TEST_ASSERT(inSuite, delegateAccessory.mNumMessageSend == 2);
108     NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1);
109
110     NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumMessageSend == 3);
111     NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1);
112 }
113
114 void SecurePairingHandshakeTest(nlTestSuite * inSuite, void * inContext)
115 {
116     TestSecurePairingDelegate delegateCommissioner;
117     PASESession pairingCommissioner;
118     SecurePairingHandshakeTestCommon(inSuite, inContext, pairingCommissioner, delegateCommissioner);
119 }
120
121 void SecurePairingDeserialize(nlTestSuite * inSuite, void * inContext, PASESession & pairingCommissioner,
122                               PASESession & deserialized)
123 {
124     PASESessionSerialized serialized;
125     NL_TEST_ASSERT(inSuite, pairingCommissioner.Serialize(serialized) == CHIP_NO_ERROR);
126
127     NL_TEST_ASSERT(inSuite, deserialized.Deserialize(serialized) == CHIP_NO_ERROR);
128
129     // Serialize from the deserialized session, and check we get the same string back
130     PASESessionSerialized serialized2;
131     NL_TEST_ASSERT(inSuite, deserialized.Serialize(serialized2) == CHIP_NO_ERROR);
132
133     NL_TEST_ASSERT(inSuite, strncmp(Uint8::to_char(serialized.inner), Uint8::to_char(serialized2.inner), sizeof(serialized)) == 0);
134 }
135
136 void SecurePairingSerializeTest(nlTestSuite * inSuite, void * inContext)
137 {
138     TestSecurePairingDelegate delegateCommissioner;
139
140     // Allocate on the heap to avoid stack overflow in some restricted test scenarios (e.g. QEMU)
141     auto * testPairingSession1 = chip::Platform::New<PASESession>();
142     auto * testPairingSession2 = chip::Platform::New<PASESession>();
143
144     SecurePairingHandshakeTestCommon(inSuite, inContext, *testPairingSession1, delegateCommissioner);
145     SecurePairingDeserialize(inSuite, inContext, *testPairingSession1, *testPairingSession2);
146
147     const uint8_t plain_text[] = { 0x86, 0x74, 0x64, 0xe5, 0x0b, 0xd4, 0x0d, 0x90, 0xe1, 0x17, 0xa3, 0x2d, 0x4b, 0xd4, 0xe1, 0xe6 };
148     uint8_t encrypted[64];
149     PacketHeader header;
150     MessageAuthenticationCode mac;
151
152     // Let's try encrypting using original session, and decrypting using deserialized
153     {
154         SecureSession session1;
155
156         NL_TEST_ASSERT(inSuite,
157                        testPairingSession1->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session1) == CHIP_NO_ERROR);
158
159         NL_TEST_ASSERT(inSuite, session1.Encrypt(plain_text, sizeof(plain_text), encrypted, header, mac) == CHIP_NO_ERROR);
160     }
161
162     {
163         SecureSession session2;
164         NL_TEST_ASSERT(inSuite,
165                        testPairingSession2->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session2) == CHIP_NO_ERROR);
166
167         uint8_t decrypted[64];
168         NL_TEST_ASSERT(inSuite, session2.Decrypt(encrypted, sizeof(plain_text), decrypted, header, mac) == CHIP_NO_ERROR);
169         NL_TEST_ASSERT(inSuite, memcmp(plain_text, decrypted, sizeof(plain_text)) == 0);
170     }
171
172     chip::Platform::Delete(testPairingSession1);
173     chip::Platform::Delete(testPairingSession2);
174 }
175
176 // Test Suite
177
178 /**
179  *  Test Suite that lists all the test functions.
180  */
181 // clang-format off
182 static const nlTest sTests[] =
183 {
184     NL_TEST_DEF("WaitInit",    SecurePairingWaitTest),
185     NL_TEST_DEF("Start",       SecurePairingStartTest),
186     NL_TEST_DEF("Handshake",   SecurePairingHandshakeTest),
187     NL_TEST_DEF("Serialize",   SecurePairingSerializeTest),
188
189     NL_TEST_SENTINEL()
190 };
191 // clang-format on
192 //
193 /**
194  *  Set up the test suite.
195  */
196 int TestSecurePairing_Setup(void * inContext)
197 {
198     CHIP_ERROR error = chip::Platform::MemoryInit();
199     if (error != CHIP_NO_ERROR)
200         return FAILURE;
201     return SUCCESS;
202 }
203
204 /**
205  *  Tear down the test suite.
206  */
207 int TestSecurePairing_Teardown(void * inContext)
208 {
209     chip::Platform::MemoryShutdown();
210     return SUCCESS;
211 }
212
213 // clang-format off
214 static nlTestSuite sSuite =
215 {
216     "Test-CHIP-SecurePairing",
217     &sTests[0],
218     TestSecurePairing_Setup,
219     TestSecurePairing_Teardown,
220 };
221 // clang-format on
222
223 /**
224  *  Main
225  */
226 int TestPASESession()
227 {
228     // Run test suit against one context
229     nlTestRunner(&sSuite, nullptr);
230
231     return (nlTestRunnerStats(&sSuite));
232 }
233
234 CHIP_REGISTER_TEST_SUITE(TestPASESession)