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 PASESession 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/PASESession.h>
37 class TestSecurePairingDelegate : public SessionEstablishmentDelegate
40 CHIP_ERROR SendSessionEstablishmentMessage(const PacketHeader & header, const Transport::PeerAddress & peerAddress,
41 System::PacketBufferHandle msgBuf) override
44 return (peer != nullptr) ? peer->HandlePeerMessage(header, peerAddress, std::move(msgBuf)) : mMessageSendError;
47 void OnSessionEstablishmentError(CHIP_ERROR error) override { mNumPairingErrors++; }
49 void OnSessionEstablished() override { mNumPairingComplete++; }
51 uint32_t mNumMessageSend = 0;
52 uint32_t mNumPairingErrors = 0;
53 uint32_t mNumPairingComplete = 0;
54 CHIP_ERROR mMessageSendError = CHIP_NO_ERROR;
56 PASESession * peer = nullptr;
59 void SecurePairingWaitTest(nlTestSuite * inSuite, void * inContext)
61 // Test all combinations of invalid parameters
62 TestSecurePairingDelegate delegate;
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);
71 void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext)
73 // Test all combinations of invalid parameters
74 TestSecurePairingDelegate delegate;
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);
80 NL_TEST_ASSERT(inSuite, delegate.mNumMessageSend == 1);
82 delegate.mMessageSendError = CHIP_ERROR_BAD_REQUEST;
86 NL_TEST_ASSERT(inSuite,
87 pairing1.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, &delegate) == CHIP_ERROR_BAD_REQUEST);
90 void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, PASESession & pairingCommissioner,
91 TestSecurePairingDelegate & delegateCommissioner)
93 // Test all combinations of invalid parameters
94 TestSecurePairingDelegate delegateAccessory;
95 PASESession pairingAccessory;
97 delegateCommissioner.peer = &pairingAccessory;
98 delegateAccessory.peer = &pairingCommissioner;
100 NL_TEST_ASSERT(inSuite,
101 pairingAccessory.WaitForPairing(1234, 500, (const uint8_t *) "saltSALT", 8, 0, &delegateAccessory) ==
103 NL_TEST_ASSERT(inSuite,
104 pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, &delegateCommissioner) ==
107 NL_TEST_ASSERT(inSuite, delegateAccessory.mNumMessageSend == 2);
108 NL_TEST_ASSERT(inSuite, delegateAccessory.mNumPairingComplete == 1);
110 NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumMessageSend == 3);
111 NL_TEST_ASSERT(inSuite, delegateCommissioner.mNumPairingComplete == 1);
114 void SecurePairingHandshakeTest(nlTestSuite * inSuite, void * inContext)
116 TestSecurePairingDelegate delegateCommissioner;
117 PASESession pairingCommissioner;
118 SecurePairingHandshakeTestCommon(inSuite, inContext, pairingCommissioner, delegateCommissioner);
121 void SecurePairingDeserialize(nlTestSuite * inSuite, void * inContext, PASESession & pairingCommissioner,
122 PASESession & deserialized)
124 PASESessionSerialized serialized;
125 NL_TEST_ASSERT(inSuite, pairingCommissioner.Serialize(serialized) == CHIP_NO_ERROR);
127 NL_TEST_ASSERT(inSuite, deserialized.Deserialize(serialized) == CHIP_NO_ERROR);
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);
133 NL_TEST_ASSERT(inSuite, strncmp(Uint8::to_char(serialized.inner), Uint8::to_char(serialized2.inner), sizeof(serialized)) == 0);
136 void SecurePairingSerializeTest(nlTestSuite * inSuite, void * inContext)
138 TestSecurePairingDelegate delegateCommissioner;
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>();
144 SecurePairingHandshakeTestCommon(inSuite, inContext, *testPairingSession1, delegateCommissioner);
145 SecurePairingDeserialize(inSuite, inContext, *testPairingSession1, *testPairingSession2);
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];
150 MessageAuthenticationCode mac;
152 // Let's try encrypting using original session, and decrypting using deserialized
154 SecureSession session1;
156 NL_TEST_ASSERT(inSuite,
157 testPairingSession1->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session1) == CHIP_NO_ERROR);
159 NL_TEST_ASSERT(inSuite, session1.Encrypt(plain_text, sizeof(plain_text), encrypted, header, mac) == CHIP_NO_ERROR);
163 SecureSession session2;
164 NL_TEST_ASSERT(inSuite,
165 testPairingSession2->DeriveSecureSession(Uint8::from_const_char("abc"), 3, session2) == CHIP_NO_ERROR);
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);
172 chip::Platform::Delete(testPairingSession1);
173 chip::Platform::Delete(testPairingSession2);
179 * Test Suite that lists all the test functions.
182 static const nlTest sTests[] =
184 NL_TEST_DEF("WaitInit", SecurePairingWaitTest),
185 NL_TEST_DEF("Start", SecurePairingStartTest),
186 NL_TEST_DEF("Handshake", SecurePairingHandshakeTest),
187 NL_TEST_DEF("Serialize", SecurePairingSerializeTest),
194 * Set up the test suite.
196 int TestSecurePairing_Setup(void * inContext)
198 CHIP_ERROR error = chip::Platform::MemoryInit();
199 if (error != CHIP_NO_ERROR)
205 * Tear down the test suite.
207 int TestSecurePairing_Teardown(void * inContext)
209 chip::Platform::MemoryShutdown();
214 static nlTestSuite sSuite =
216 "Test-CHIP-SecurePairing",
218 TestSecurePairing_Setup,
219 TestSecurePairing_Teardown,
226 int TestPASESession()
228 // Run test suit against one context
229 nlTestRunner(&sSuite, nullptr);
231 return (nlTestRunnerStats(&sSuite));
234 CHIP_REGISTER_TEST_SUITE(TestPASESession)