-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
512f5c8
commit 51fa4b6
Showing
6 changed files
with
316 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
/* | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <app/InteractionModelEngine.h> | ||
#include <app/icd/client/CheckInHandler.h> | ||
#include <app/icd/client/DefaultCheckInDelegate.h> | ||
#include <app/icd/client/DefaultICDClientStorage.h> | ||
#include <app/reporting/tests/MockReportScheduler.h> | ||
#include <app/tests/AppTestContext.h> | ||
#include <crypto/DefaultSessionKeystore.h> | ||
#include <lib/core/StringBuilderAdapters.h> | ||
#include <lib/support/DefaultStorageKeyAllocator.h> | ||
#include <lib/support/Span.h> | ||
#include <lib/support/TestPersistentStorageDelegate.h> | ||
#include <protocols/secure_channel/CheckinMessage.h> | ||
#include <pw_unit_test/framework.h> | ||
#include <system/SystemPacketBuffer.h> | ||
#include <transport/SessionManager.h> | ||
|
||
using namespace chip; | ||
using namespace app; | ||
using namespace System; | ||
using TestSessionKeystoreImpl = Crypto::DefaultSessionKeystore; | ||
|
||
constexpr uint8_t kKeyBuffer1[] = { | ||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f | ||
}; | ||
|
||
constexpr uint8_t kKeyBuffer2[] = { | ||
0xf1, 0xe1, 0xd1, 0xc1, 0xb1, 0xa1, 0x91, 0x81, 0x71, 0x61, 0x51, 0x14, 0x31, 0x21, 0x11, 0x01 | ||
}; | ||
|
||
class TestCheckInHandler : public chip::Test::AppContext | ||
{ | ||
}; | ||
|
||
class CheckInHandlerWrapper : public chip::app::CheckInHandler | ||
{ | ||
public: | ||
CHIP_ERROR ValidateOnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, | ||
System::PacketBufferHandle && payload) | ||
{ | ||
return OnMessageReceived(ec, payloadHeader, std::move(payload)); | ||
} | ||
}; | ||
|
||
TEST_F(TestCheckInHandler, TestOnMessageReceived) | ||
{ | ||
InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); | ||
EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); | ||
TestPersistentStorageDelegate clientInfoStorage; | ||
TestSessionKeystoreImpl keystore; | ||
|
||
DefaultICDClientStorage manager; | ||
EXPECT_EQ(manager.Init(&clientInfoStorage, &keystore), CHIP_NO_ERROR); | ||
|
||
DefaultCheckInDelegate checkInDelegate; | ||
EXPECT_EQ(checkInDelegate.Init(&manager, engine), CHIP_NO_ERROR); | ||
|
||
CheckInHandlerWrapper checkInHandler; | ||
EXPECT_EQ(checkInHandler.Init(&GetExchangeManager(), &manager, &checkInDelegate, engine), CHIP_NO_ERROR); | ||
|
||
FabricIndex fabricIdA = 1; | ||
NodeId nodeIdA = 6666; | ||
|
||
ICDClientInfo clientInfoA; | ||
clientInfoA.peer_node = ScopedNodeId(nodeIdA, fabricIdA); | ||
clientInfoA.start_icd_counter = 0; | ||
clientInfoA.offset = 0; | ||
EXPECT_EQ(manager.UpdateFabricList(fabricIdA), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.SetKey(clientInfoA, ByteSpan(kKeyBuffer1)), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.StoreEntry(clientInfoA), CHIP_NO_ERROR); | ||
|
||
FabricIndex fabricIdB = 2; | ||
NodeId nodeIdB = 6667; | ||
|
||
ICDClientInfo clientInfoB; | ||
clientInfoB.peer_node = ScopedNodeId(nodeIdB, fabricIdB); | ||
clientInfoB.offset = 0; | ||
EXPECT_EQ(manager.UpdateFabricList(fabricIdB), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.SetKey(clientInfoB, ByteSpan(kKeyBuffer2)), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.StoreEntry(clientInfoB), CHIP_NO_ERROR); | ||
|
||
PayloadHeader payloadHeader; | ||
payloadHeader.SetExchangeID(0); | ||
payloadHeader.SetMessageType(chip::Protocols::SecureChannel::MsgType::ICD_CheckIn); | ||
|
||
uint32_t counter = 1; | ||
System::PacketBufferHandle buffer1 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output1{ buffer1->Start(), buffer1->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoA.aes_key_handle, clientInfoA.hmac_key_handle, counter, ByteSpan(), output1), | ||
CHIP_NO_ERROR); | ||
|
||
buffer1->SetDataLength(static_cast<uint16_t>(output1.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer1)), CHIP_NO_ERROR); | ||
|
||
ICDClientInfo clientInfo1; | ||
auto * iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo1)) | ||
{ | ||
if (clientInfo1.peer_node.GetNodeId() == nodeIdA && clientInfo1.peer_node.GetFabricIndex() == fabricIdA) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
|
||
EXPECT_EQ(clientInfo1.offset, counter - clientInfoA.start_icd_counter); | ||
|
||
// Validate duplicate check-in message handling | ||
chip::System::PacketBufferHandle buffer2 = | ||
MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output2{ buffer2->Start(), buffer2->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoA.aes_key_handle, clientInfoA.hmac_key_handle, counter, ByteSpan(), output2), | ||
CHIP_NO_ERROR); | ||
|
||
buffer2->SetDataLength(static_cast<uint16_t>(output2.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer2)), CHIP_NO_ERROR); | ||
|
||
ICDClientInfo clientInfo2; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo2)) | ||
{ | ||
if (clientInfo2.peer_node.GetNodeId() == nodeIdA && clientInfo2.peer_node.GetFabricIndex() == fabricIdA) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo2.offset, counter - clientInfoA.start_icd_counter); | ||
|
||
// Validate second check-in message with increased counter | ||
counter++; | ||
System::PacketBufferHandle buffer3 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output3{ buffer3->Start(), buffer3->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoA.aes_key_handle, clientInfoA.hmac_key_handle, counter, ByteSpan(), output3), | ||
CHIP_NO_ERROR); | ||
buffer3->SetDataLength(static_cast<uint16_t>(output3.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer3)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo3; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo3)) | ||
{ | ||
if (clientInfo3.peer_node.GetNodeId() == nodeIdA && clientInfo3.peer_node.GetFabricIndex() == fabricIdA) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo3.offset, counter - clientInfoA.start_icd_counter); | ||
|
||
// Validate check-in message from fabricB | ||
counter++; | ||
System::PacketBufferHandle buffer4 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output4{ buffer4->Start(), buffer4->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoB.aes_key_handle, clientInfoB.hmac_key_handle, counter, ByteSpan(), output4), | ||
CHIP_NO_ERROR); | ||
buffer4->SetDataLength(static_cast<uint16_t>(output4.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer4)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo4; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo4)) | ||
{ | ||
if (clientInfo4.peer_node.GetNodeId() == nodeIdB && clientInfo4.peer_node.GetFabricIndex() == fabricIdB) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo4.offset, counter - clientInfoB.start_icd_counter); | ||
|
||
// Validate check-in message from removed fabricB | ||
counter++; | ||
System::PacketBufferHandle buffer5 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output5{ buffer5->Start(), buffer5->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoB.aes_key_handle, clientInfoB.hmac_key_handle, counter, ByteSpan(), output5), | ||
CHIP_NO_ERROR); | ||
|
||
EXPECT_EQ(manager.DeleteAllEntries(fabricIdB), CHIP_NO_ERROR); | ||
buffer5->SetDataLength(static_cast<uint16_t>(output5.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer5)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo5; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
bool located = false; | ||
while (iterator->Next(clientInfo5)) | ||
{ | ||
if (clientInfo5.peer_node.GetFabricIndex() == fabricIdB) | ||
{ | ||
located = true; | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_FALSE(located); | ||
|
||
// Add back fabricB and validate check-in message again | ||
EXPECT_EQ(manager.UpdateFabricList(fabricIdB), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.SetKey(clientInfoB, ByteSpan(kKeyBuffer2)), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.StoreEntry(clientInfoB), CHIP_NO_ERROR); | ||
counter++; | ||
System::PacketBufferHandle buffer6 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output6{ buffer6->Start(), buffer6->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoB.aes_key_handle, clientInfoB.hmac_key_handle, counter, ByteSpan(), output6), | ||
CHIP_NO_ERROR); | ||
buffer6->SetDataLength(static_cast<uint16_t>(output4.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer6)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo6; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo6)) | ||
{ | ||
if (clientInfo6.peer_node.GetNodeId() == nodeIdB && clientInfo6.peer_node.GetFabricIndex() == fabricIdB) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo6.offset, counter - clientInfoB.start_icd_counter); | ||
|
||
// Clear fabric table | ||
EXPECT_EQ(manager.DeleteAllEntries(fabricIdA), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.DeleteAllEntries(fabricIdB), CHIP_NO_ERROR); | ||
// Add back fabricA and validate check-in message again | ||
EXPECT_EQ(manager.UpdateFabricList(fabricIdA), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.SetKey(clientInfoA, ByteSpan(kKeyBuffer1)), CHIP_NO_ERROR); | ||
EXPECT_EQ(manager.StoreEntry(clientInfoA), CHIP_NO_ERROR); | ||
counter++; | ||
System::PacketBufferHandle buffer7 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output7{ buffer7->Start(), buffer7->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoA.aes_key_handle, clientInfoA.hmac_key_handle, counter, ByteSpan(), output7), | ||
CHIP_NO_ERROR); | ||
buffer7->SetDataLength(static_cast<uint16_t>(output7.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer7)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo7; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo7)) | ||
{ | ||
if (clientInfo7.peer_node.GetNodeId() == nodeIdA && clientInfo7.peer_node.GetFabricIndex() == fabricIdA) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo7.offset, counter - clientInfoA.start_icd_counter); | ||
|
||
// Validate IcdclientInfo is not updated when handling overlimited counter and fail to create case session | ||
uint32_t old_start_icd_counter = clientInfo7.start_icd_counter; | ||
uint32_t old_counter = counter; | ||
counter = (1U << 31) + 100U + clientInfo7.start_icd_counter; | ||
System::PacketBufferHandle buffer8 = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); | ||
MutableByteSpan output8{ buffer8->Start(), buffer8->MaxDataLength() }; | ||
EXPECT_EQ(chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( | ||
clientInfoA.aes_key_handle, clientInfoA.hmac_key_handle, counter, ByteSpan(), output8), | ||
CHIP_NO_ERROR); | ||
|
||
buffer8->SetDataLength(static_cast<uint16_t>(output8.size())); | ||
EXPECT_EQ(checkInHandler.ValidateOnMessageReceived(nullptr, payloadHeader, std::move(buffer8)), CHIP_NO_ERROR); | ||
ICDClientInfo clientInfo8; | ||
iterator = manager.IterateICDClientInfo(); | ||
ASSERT_NE(iterator, nullptr); | ||
while (iterator->Next(clientInfo8)) | ||
{ | ||
if (clientInfo8.peer_node.GetNodeId() == nodeIdA && clientInfo8.peer_node.GetFabricIndex() == fabricIdA) | ||
{ | ||
break; | ||
} | ||
} | ||
iterator->Release(); | ||
EXPECT_EQ(clientInfo8.offset, old_counter - clientInfoA.start_icd_counter); | ||
EXPECT_EQ(clientInfo8.start_icd_counter, old_start_icd_counter); | ||
|
||
checkInHandler.Shutdown(); | ||
} |
Oops, something went wrong.