3 * Copyright (c) 2020 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 SecurePairingSession implementation.
25 #include <nlunit-test.h>
27 #include <core/CHIPCore.h>
28 #include <core/CHIPSafeCasts.h>
30 #include <support/CHIPMem.h>
31 #include <support/CodeUtils.h>
32 #include <support/UnitTestRegistration.h>
33 #include <transport/SecurePairingSession.h>
37 class TestSecurePairingDelegate : public SecurePairingSessionDelegate
40 CHIP_ERROR SendPairingMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress,
41 System::PacketBuffer * msgBuf) override
44 System::PacketBufferHandle msg_ForNow;
45 msg_ForNow.Adopt(msgBuf);
46 return (peer != nullptr) ? peer->HandlePeerMessage(header, peerAddress, std::move(msg_ForNow)) : mMessageSendError;
49 void OnPairingError(CHIP_ERROR error) override { mNumPairingErrors++; }
51 void OnPairingComplete() override { mNumPairingComplete++; }
53 uint32_t mNumMessageSend = 0;
54 uint32_t mNumPairingErrors = 0;
55 uint32_t mNumPairingComplete = 0;
56 CHIP_ERROR mMessageSendError = CHIP_NO_ERROR;
58 SecurePairingSession * peer = nullptr;
61 void SecurePairingWaitTest(nlTestSuite * inSuite, void * inContext)
63 // Test all combinations of invalid parameters
64 TestSecurePairingDelegate delegate;
65 SecurePairingSession pairing;
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) ==
78 void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext)
80 // Test all combinations of invalid parameters
81 TestSecurePairingDelegate delegate;
82 SecurePairingSession pairing;
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);
94 NL_TEST_ASSERT(inSuite, delegate.mNumMessageSend == 1);
96 delegate.mMessageSendError = CHIP_ERROR_BAD_REQUEST;
98 SecurePairingSession pairing1;
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);
105 void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, SecurePairingSession & pairingCommissioner,
106 TestSecurePairingDelegate & delegateCommissioner)
108 // Test all combinations of invalid parameters
109 TestSecurePairingDelegate delegateAccessory;
110 SecurePairingSession pairingAccessory;
112 delegateCommissioner.peer = &pairingAccessory;
113 delegateAccessory.peer = &pairingCommissioner;
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);
122 NL_TEST_ASSERT(inSuite, delegateAccessory.mNumMessageSend == 1);
123 NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1);
125 NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumMessageSend == 2);
126 NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1);
129 void SecurePairingHandshakeTest(nlTestSuite * inSuite, void * inContext)
131 TestSecurePairingDelegate delegateCommissioner;
132 SecurePairingSession pairingCommissioner;
133 SecurePairingHandshakeTestCommon(inSuite, inContext, pairingCommissioner, delegateCommissioner);
136 void SecurePairingDeserialize(nlTestSuite * inSuite, void * inContext, SecurePairingSession & pairingCommissioner,
137 SecurePairingSession & deserialized)
139 SecurePairingSessionSerialized serialized;
140 NL_TEST_ASSERT(inSuite, pairingCommissioner.Serialize(serialized) == CHIP_NO_ERROR);
142 NL_TEST_ASSERT(inSuite, deserialized.Deserialize(serialized) == CHIP_NO_ERROR);
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);
148 NL_TEST_ASSERT(inSuite, strncmp(Uint8::to_char(serialized.inner), Uint8::to_char(serialized2.inner), sizeof(serialized)) == 0);
151 void SecurePairingSerializeTest(nlTestSuite * inSuite, void * inContext)
153 TestSecurePairingDelegate delegateCommissioner;
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>();
159 SecurePairingHandshakeTestCommon(inSuite, inContext, *testPairingSession1, delegateCommissioner);
160 SecurePairingDeserialize(inSuite, inContext, *testPairingSession1, *testPairingSession2);
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];
165 MessageAuthenticationCode mac;
167 // Let's try encrypting using original session, and decrypting using deserialized
169 SecureSession session1;
171 NL_TEST_ASSERT(inSuite,
172 testPairingSession1->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session1) == CHIP_NO_ERROR);
174 NL_TEST_ASSERT(inSuite, session1.Encrypt(plain_text, sizeof(plain_text), encrypted, header, mac) == CHIP_NO_ERROR);
178 SecureSession session2;
179 NL_TEST_ASSERT(inSuite,
180 testPairingSession2->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session2) == CHIP_NO_ERROR);
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);
187 chip::Platform::Delete(testPairingSession1);
188 chip::Platform::Delete(testPairingSession2);
194 * Test Suite that lists all the test functions.
197 static const nlTest sTests[] =
199 NL_TEST_DEF("WaitInit", SecurePairingWaitTest),
200 NL_TEST_DEF("Start", SecurePairingStartTest),
201 NL_TEST_DEF("Handshake", SecurePairingHandshakeTest),
202 NL_TEST_DEF("Serialize", SecurePairingSerializeTest),
209 * Set up the test suite.
211 int TestSecurePairing_Setup(void * inContext)
213 CHIP_ERROR error = chip::Platform::MemoryInit();
214 if (error != CHIP_NO_ERROR)
220 * Tear down the test suite.
222 int TestSecurePairing_Teardown(void * inContext)
224 chip::Platform::MemoryShutdown();
229 static nlTestSuite sSuite =
231 "Test-CHIP-SecurePairing",
233 TestSecurePairing_Setup,
234 TestSecurePairing_Teardown,
241 int TestSecurePairingSession()
243 // Run test suit against one context
244 nlTestRunner(&sSuite, nullptr);
246 return (nlTestRunnerStats(&sSuite));
249 CHIP_REGISTER_TEST_SUITE(TestSecurePairingSession)
253 void LogV(uint8_t module, uint8_t category, const char * format, va_list argptr)
255 (void) module, (void) category;
256 vfprintf(stderr, format, argptr);
258 } // namespace Logging