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