diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 7a0b440ad536dc..53568316114c9a 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -102,6 +102,7 @@ static_library("chip-tool-utils") { public_deps = [ "${chip_root}/examples/common/tracing:commandline", + "${chip_root}/src/app/icd/client:handler", "${chip_root}/src/app/icd/client:manager", "${chip_root}/src/app/server", "${chip_root}/src/app/tests/suites/commands/interaction_model", diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 7e721734cd1a80..45fc2105183cdc 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -50,6 +50,8 @@ chip::Credentials::GroupDataProviderImpl CHIPCommand::sGroupDataProvider{ kMaxGr // All fabrics share the same ICD client storage. chip::app::DefaultICDClientStorage CHIPCommand::sICDClientStorage; chip::Crypto::RawKeySessionKeystore CHIPCommand::sSessionKeystore; +chip::app::DefaultCheckInDelegate CHIPCommand::sCheckInDelegate; +chip::app::CheckInHandler CHIPCommand::sCheckInHandler; namespace { @@ -139,6 +141,10 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() ReturnErrorOnFailure(GetAttestationTrustStore(mPaaTrustStorePath.ValueOr(nullptr), &sTrustStore)); + ReturnLogErrorOnFailure(sCheckInDelegate.Init(&sICDClientStorage)); + ReturnLogErrorOnFailure(sCheckInHandler.Init(DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), + &sICDClientStorage, &sCheckInDelegate)); + CommissionerIdentity nullIdentity{ kIdentityNull, chip::kUndefinedNodeId }; ReturnLogErrorOnFailure(InitializeCommissioner(nullIdentity, kIdentityNullFabricId)); diff --git a/examples/chip-tool/commands/common/CHIPCommand.h b/examples/chip-tool/commands/common/CHIPCommand.h index 3376e47ba0f20d..2caf6fe9cc94ec 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.h +++ b/examples/chip-tool/commands/common/CHIPCommand.h @@ -25,6 +25,8 @@ #include "Command.h" #include +#include +#include #include #include #include @@ -160,6 +162,8 @@ class CHIPCommand : public Command static chip::Credentials::GroupDataProviderImpl sGroupDataProvider; static chip::app::DefaultICDClientStorage sICDClientStorage; + static chip::app::DefaultCheckInDelegate sCheckInDelegate; + static chip::app::CheckInHandler sCheckInHandler; CredentialIssuerCommands * mCredIssuerCmds; std::string GetIdentity(); diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index b9f458bb00b367..d9c391b1e1b037 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -118,6 +118,7 @@ chip_data_model("tv-casting-common") { deps = [ "${chip_root}/examples/common/tracing:commandline", + "${chip_root}/src/app/icd/client:handler", "${chip_root}/src/app/icd/client:manager", "${chip_root}/src/app/tests/suites/commands/interaction_model", "${chip_root}/src/lib/support/jsontlv", diff --git a/src/app/icd/client/BUILD.gn b/src/app/icd/client/BUILD.gn index 8e04d3b586140f..fa32e9c68dbfd4 100644 --- a/src/app/icd/client/BUILD.gn +++ b/src/app/icd/client/BUILD.gn @@ -28,5 +28,25 @@ source_set("manager") { "${chip_root}/src/app:app_config", "${chip_root}/src/crypto", "${chip_root}/src/lib/support", + "${chip_root}/src/protocols", + ] +} + +# ICD Handler source-set is broken out of the main source-set to enable unit tests +# All sources and configurations used by the CheckInHandler need to go in this source-set +source_set("handler") { + sources = [ + "CheckInDelegate.h", + "CheckInHandler.cpp", + "CheckInHandler.h", + "DefaultCheckInDelegate.cpp", + "DefaultCheckInDelegate.h", + ] + public_deps = [ + ":manager", + "${chip_root}/src/app", + "${chip_root}/src/lib/core", + "${chip_root}/src/messaging", + "${chip_root}/src/protocols", ] } diff --git a/src/app/icd/client/CheckInDelegate.h b/src/app/icd/client/CheckInDelegate.h new file mode 100644 index 00000000000000..50d378a87a58e7 --- /dev/null +++ b/src/app/icd/client/CheckInDelegate.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include + +namespace chip { +namespace app { + +/// Callbacks for check in protocol +/** + * @brief The application implementing an ICD client should inherit the CheckInDelegate and implement the listed callbacks + */ +class DLL_EXPORT CheckInDelegate +{ +public: + virtual ~CheckInDelegate() {} + + /** + * @brief Callback used to let the application know that a check-in message was received and validated. + * + * @param[in] clientInfo - ICDClientInfo object representing the state associated with the + node that sent the check-in message. + */ + virtual void OnCheckInComplete(const ICDClientInfo & clientInfo) = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/icd/client/CheckInHandler.cpp b/src/app/icd/client/CheckInHandler.cpp new file mode 100644 index 00000000000000..f05dcd8b7819ed --- /dev/null +++ b/src/app/icd/client/CheckInHandler.cpp @@ -0,0 +1,126 @@ +/* + * + * Copyright (c) 2023 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. + */ + +/** + * @file + * This file defines objects for a CHIP ICD handler which handles unsolicited check-in messages. + * + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +namespace chip { +namespace app { + +inline constexpr uint64_t kCheckInCounterMax = (1ULL << 32); +inline constexpr uint32_t kKeyRefreshLimit = (1U << 31); + +CheckInHandler::CheckInHandler() {} + +CHIP_ERROR CheckInHandler::Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, + CheckInDelegate * delegate) +{ + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(clientStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(mpExchangeManager == nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mpICDClientStorage == nullptr, CHIP_ERROR_INCORRECT_STATE); + + mpExchangeManager = exchangeManager; + mpICDClientStorage = clientStorage; + mpCheckInDelegate = delegate; + + return mpExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn, this); +} + +void CheckInHandler::Shutdown() +{ + mpICDClientStorage = nullptr; + mpCheckInDelegate = nullptr; + if (mpExchangeManager) + { + mpExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn); + mpExchangeManager = nullptr; + } +} + +CHIP_ERROR CheckInHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) +{ + // Return error for wrong message type + VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn), + CHIP_ERROR_INVALID_MESSAGE_TYPE); + + newDelegate = this; + return CHIP_NO_ERROR; +} + +CHIP_ERROR CheckInHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) +{ + // If the message type is not ICD_CheckIn, return CHIP_NO_ERROR and exit + VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn), CHIP_NO_ERROR); + + ByteSpan payloadByteSpan{ payload->Start(), payload->DataLength() }; + ICDClientInfo clientInfo; + CounterType counter = 0; + // If the check-in message processing fails, return CHIP_NO_ERROR and exit. + CHIP_ERROR err = mpICDClientStorage->ProcessCheckInPayload(payloadByteSpan, clientInfo, counter); + if (CHIP_NO_ERROR != err) + { + ChipLogError(ICD, "ProcessCheckInPayload failed: %" CHIP_ERROR_FORMAT, err.Format()); + return CHIP_NO_ERROR; + } + CounterType receivedCheckInCounterOffset = (counter - clientInfo.start_icd_counter) % kCheckInCounterMax; + + // Detect duplicate check-in messages and return CHIP_NO_ERROR on receiving a duplicate message + if (receivedCheckInCounterOffset <= clientInfo.offset) + { + ChipLogError(ICD, "A duplicate check-in message was received and discarded"); + return CHIP_NO_ERROR; + } + + clientInfo.offset = receivedCheckInCounterOffset; + bool refreshKey = (receivedCheckInCounterOffset > kKeyRefreshLimit); + + if (refreshKey) + { + // TODO: A new CASE session should be established to re-register the client using a new key. The registration will happen in + // CASE session callback + } + else + { + mpCheckInDelegate->OnCheckInComplete(clientInfo); + } + + return CHIP_NO_ERROR; +} + +void CheckInHandler::OnResponseTimeout(Messaging::ExchangeContext * ec) {} + +} // namespace app +} // namespace chip diff --git a/src/app/icd/client/CheckInHandler.h b/src/app/icd/client/CheckInHandler.h new file mode 100644 index 00000000000000..22170a1b332694 --- /dev/null +++ b/src/app/icd/client/CheckInHandler.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2023 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. + */ + +/** + * @file + * This file defines objects for a CHIP check-in message unsolicited + * handler + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +class CheckInHandler : public Messaging::ExchangeDelegate, public Messaging::UnsolicitedMessageHandler +{ + +public: + CHIP_ERROR Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, CheckInDelegate * delegate); + void Shutdown(); + + CheckInHandler(); + + virtual ~CheckInHandler() = default; + +protected: + // ExchangeDelegate + CHIP_ERROR + OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) override; + + // UnsolicitedMessageHandler + CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override; + + // TODO : Follow up to check if this really needs to be a pure virtual function in Exchange delegate + // https://github.com/project-chip/connectedhomeip/issues/31322 + void OnResponseTimeout(Messaging::ExchangeContext * ec) override; + + Messaging::ExchangeMessageDispatch & GetMessageDispatch() override { return CheckInExchangeDispatch::Instance(); } + +private: + class CheckInExchangeDispatch : public Messaging::ExchangeMessageDispatch + { + public: + static ExchangeMessageDispatch & Instance() + { + static CheckInExchangeDispatch instance; + return instance; + } + + CheckInExchangeDispatch() {} + ~CheckInExchangeDispatch() override {} + + protected: + bool MessagePermitted(Protocols::Id, uint8_t type) override + { + return type == to_underlying(Protocols::SecureChannel::MsgType::ICD_CheckIn); + } + bool IsEncryptionRequired() const override { return false; } + }; + + Messaging::ExchangeManager * mpExchangeManager = nullptr; + CheckInDelegate * mpCheckInDelegate = nullptr; + ICDClientStorage * mpICDClientStorage = nullptr; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/icd/client/DefaultCheckInDelegate.cpp b/src/app/icd/client/DefaultCheckInDelegate.cpp new file mode 100644 index 00000000000000..33f6631f2563fb --- /dev/null +++ b/src/app/icd/client/DefaultCheckInDelegate.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 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 "CheckInHandler.h" +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +CHIP_ERROR DefaultCheckInDelegate::Init(ICDClientStorage * storage) +{ + VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(mpStorage == nullptr, CHIP_ERROR_INCORRECT_STATE); + mpStorage = storage; + return CHIP_NO_ERROR; +} + +void DefaultCheckInDelegate::OnCheckInComplete(const ICDClientInfo & clientInfo) +{ + ChipLogProgress( + ICD, "Check In Message processing complete: start_counter=%" PRIu32 " offset=%" PRIu32 " nodeid=" ChipLogFormatScopedNodeId, + clientInfo.start_icd_counter, clientInfo.offset, ChipLogValueScopedNodeId(clientInfo.peer_node)); +} + +} // namespace app +} // namespace chip diff --git a/src/app/icd/client/DefaultCheckInDelegate.h b/src/app/icd/client/DefaultCheckInDelegate.h new file mode 100644 index 00000000000000..5e77186b3c7c9d --- /dev/null +++ b/src/app/icd/client/DefaultCheckInDelegate.h @@ -0,0 +1,42 @@ +/* + * + * Copyright (c) 2023 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. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace app { + +using namespace std; + +/// Callbacks for check in protocol +class DefaultCheckInDelegate : public CheckInDelegate +{ +public: + virtual ~DefaultCheckInDelegate() {} + CHIP_ERROR Init(ICDClientStorage * storage); + void OnCheckInComplete(const ICDClientInfo & clientInfo) override; + +private: + ICDClientStorage * mpStorage = nullptr; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/icd/client/DefaultICDClientStorage.cpp b/src/app/icd/client/DefaultICDClientStorage.cpp index c2c6cdfe95142e..7ada84287fa4df 100644 --- a/src/app/icd/client/DefaultICDClientStorage.cpp +++ b/src/app/icd/client/DefaultICDClientStorage.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "DefaultICDClientStorage.h" +#include #include #include #include @@ -462,10 +462,25 @@ CHIP_ERROR DefaultICDClientStorage::DeleteAllEntries(FabricIndex fabricIndex) return mpClientInfoStore->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricICDClientInfoCounter(fabricIndex).KeyName()); } -CHIP_ERROR DefaultICDClientStorage::ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo) +CHIP_ERROR DefaultICDClientStorage::ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo, + CounterType & counter) { - // TODO: Need to implement default decription code using CheckinMessage::ParseCheckinMessagePayload - return CHIP_NO_ERROR; + uint8_t appDataBuffer[kAppDataLength]; + MutableByteSpan appData(appDataBuffer); + auto * iterator = IterateICDClientInfo(); + VerifyOrReturnError(iterator != nullptr, CHIP_ERROR_NO_MEMORY); + while (iterator->Next(clientInfo)) + { + CHIP_ERROR err = chip::Protocols::SecureChannel::CheckinMessage::ParseCheckinMessagePayload( + clientInfo.aes_key_handle, clientInfo.hmac_key_handle, payload, counter, appData); + if (CHIP_NO_ERROR == err) + { + iterator->Release(); + return CHIP_NO_ERROR; + } + } + iterator->Release(); + return CHIP_ERROR_NOT_FOUND; } } // namespace app } // namespace chip diff --git a/src/app/icd/client/DefaultICDClientStorage.h b/src/app/icd/client/DefaultICDClientStorage.h index 0d398469a30ff4..1f6c2f8eb14a2c 100644 --- a/src/app/icd/client/DefaultICDClientStorage.h +++ b/src/app/icd/client/DefaultICDClientStorage.h @@ -21,7 +21,7 @@ #pragma once -#include "ICDClientStorage.h" +#include #include #include @@ -95,7 +95,7 @@ class DefaultICDClientStorage : public ICDClientStorage */ CHIP_ERROR DeleteAllEntries(FabricIndex fabricIndex); - CHIP_ERROR ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo) override; + CHIP_ERROR ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo, CounterType & counter) override; protected: enum class ClientInfoTag : uint8_t diff --git a/src/app/icd/client/ICDClientStorage.h b/src/app/icd/client/ICDClientStorage.h index d4727ffac6030e..d65a64ff8c21a8 100644 --- a/src/app/icd/client/ICDClientStorage.h +++ b/src/app/icd/client/ICDClientStorage.h @@ -24,11 +24,14 @@ #include #include #include +#include +#include #include namespace chip { namespace app { +using namespace Protocols::SecureChannel; /** * The ICDClientStorage class is an abstract interface that defines the operations * for storing, retrieving and deleting ICD client information in persistent storage. @@ -71,13 +74,17 @@ class ICDClientStorage virtual CHIP_ERROR DeleteEntry(const ScopedNodeId & peerNode) = 0; /** - * Process received ICD Check-in message payload. The implementation needs to parse the payload, + * Process received ICD check-in message payload. The implementation needs to parse the payload, * look for a key that allows successfully decrypting the payload, verify that the counter in the payload is valid, * and populate the clientInfo with the stored information corresponding to the key. - * @param[in] payload received checkIn Message payload + * @param[in] payload received check-in Message payload * @param[out] clientInfo retrieved matched clientInfo from storage + * @param[out] counter counter value received in the check-in message */ - virtual CHIP_ERROR ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo) = 0; + virtual CHIP_ERROR ProcessCheckInPayload(const ByteSpan & payload, ICDClientInfo & clientInfo, CounterType & counter) = 0; + + // 4 bytes for counter + 2 bytes for ActiveModeThreshold + static inline constexpr uint8_t kAppDataLength = 6; }; } // namespace app } // namespace chip diff --git a/src/app/tests/TestDefaultICDClientStorage.cpp b/src/app/tests/TestDefaultICDClientStorage.cpp index 9bb11ccd734476..e5e0024c0022f0 100644 --- a/src/app/tests/TestDefaultICDClientStorage.cpp +++ b/src/app/tests/TestDefaultICDClientStorage.cpp @@ -15,13 +15,17 @@ * limitations under the License. */ +#include #include #include +#include #include #include #include #include +#include +#include using namespace chip; using namespace app; @@ -196,6 +200,55 @@ void TestClientInfoCountMultipleFabric(nlTestSuite * apSuite, void * apContext) NL_TEST_ASSERT(apSuite, count == 0); } +void TestProcessCheckInPayload(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + FabricIndex fabricId = 1; + NodeId nodeId = 6666; + TestPersistentStorageDelegate clientInfoStorage; + TestSessionKeystoreImpl keystore; + + DefaultICDClientStorage manager; + err = manager.Init(&clientInfoStorage, &keystore); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = manager.UpdateFabricList(fabricId); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + // Populate clientInfo + ICDClientInfo clientInfo; + clientInfo.peer_node = ScopedNodeId(nodeId, fabricId); + + err = manager.SetKey(clientInfo, ByteSpan(kKeyBuffer1)); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = manager.StoreEntry(clientInfo); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + uint32_t counter = 1; + System::PacketBufferHandle buffer = MessagePacketBuffer::New(chip::Protocols::SecureChannel::CheckinMessage::kMinPayloadSize); + MutableByteSpan output{ buffer->Start(), buffer->MaxDataLength() }; + err = chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( + clientInfo.aes_key_handle, clientInfo.hmac_key_handle, counter, ByteSpan(), output); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + buffer->SetDataLength(static_cast(output.size())); + ICDClientInfo decodeClientInfo; + uint32_t checkInCounter = 0; + ByteSpan payload{ buffer->Start(), buffer->DataLength() }; + err = manager.ProcessCheckInPayload(payload, decodeClientInfo, checkInCounter); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + // 2. Use a key not available in the storage for encoding + err = manager.SetKey(clientInfo, ByteSpan(kKeyBuffer2)); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + err = chip::Protocols::SecureChannel::CheckinMessage::GenerateCheckinMessagePayload( + clientInfo.aes_key_handle, clientInfo.hmac_key_handle, counter, ByteSpan(), output); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + buffer->SetDataLength(static_cast(output.size())); + ByteSpan payload1{ buffer->Start(), buffer->DataLength() }; + err = manager.ProcessCheckInPayload(payload1, decodeClientInfo, checkInCounter); + NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_FOUND); +} + /** * Set up the test suite. */ @@ -225,6 +278,8 @@ static const nlTest sTests[] = { NL_TEST_DEF("TestClientInfoCount", TestClientInfoCount), NL_TEST_DEF("TestClientInfoCountMultipleFabric", TestClientInfoCountMultipleFabric), + NL_TEST_DEF("TestProcessCheckInPayload", TestProcessCheckInPayload), + NL_TEST_SENTINEL() }; // clang-format on diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index ecb775027b45f6..c0fe3837c6b063 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -65,6 +65,7 @@ shared_library("jni") { ] deps = [ + "${chip_root}/src/app/icd/client:handler", "${chip_root}/src/app/icd/client:manager", "${chip_root}/src/credentials:default_attestation_verifier", "${chip_root}/src/inet", diff --git a/src/lib/support/logging/Constants.h b/src/lib/support/logging/Constants.h index 5abf073bf48a68..6a176b02eb1389 100644 --- a/src/lib/support/logging/Constants.h +++ b/src/lib/support/logging/Constants.h @@ -59,6 +59,7 @@ enum LogModule kLogModule_OperationalSessionSetup, kLogModule_Automation, kLogModule_CASESessionManager, + kLogModule_ICD, kLogModule_Max }; @@ -226,6 +227,10 @@ enum LogModule #define CHIP_CONFIG_LOG_MODULE_CASESessionManager 1 #endif +#ifndef CHIP_CONFIG_LOG_MODULE_ICD +#define CHIP_CONFIG_LOG_MODULE_ICD 1 +#endif + /** * @enum LogCategory * diff --git a/src/protocols/secure_channel/CheckinMessage.cpp b/src/protocols/secure_channel/CheckinMessage.cpp index 24fd07fba6be4f..972b61c35ff0c0 100644 --- a/src/protocols/secure_channel/CheckinMessage.cpp +++ b/src/protocols/secure_channel/CheckinMessage.cpp @@ -75,7 +75,7 @@ CHIP_ERROR CheckinMessage::GenerateCheckinMessagePayload(const Crypto::Aes128Key } CHIP_ERROR CheckinMessage::ParseCheckinMessagePayload(const Crypto::Aes128KeyHandle & aes128KeyHandle, - const Crypto::Hmac128KeyHandle & hmacKeyHandle, ByteSpan & payload, + const Crypto::Hmac128KeyHandle & hmacKeyHandle, const ByteSpan & payload, CounterType & counter, MutableByteSpan & appData) { size_t appDataSize = GetAppDataSize(payload); @@ -153,7 +153,7 @@ CHIP_ERROR CheckinMessage::GenerateCheckInMessageNonce(const Crypto::Hmac128KeyH return CHIP_NO_ERROR; } -size_t CheckinMessage::GetAppDataSize(ByteSpan & payload) +size_t CheckinMessage::GetAppDataSize(const ByteSpan & payload) { return (payload.size() <= kMinPayloadSize) ? 0 : payload.size() - kMinPayloadSize; } diff --git a/src/protocols/secure_channel/CheckinMessage.h b/src/protocols/secure_channel/CheckinMessage.h index a0123f3749ce2b..0750c3cf319f94 100644 --- a/src/protocols/secure_channel/CheckinMessage.h +++ b/src/protocols/secure_channel/CheckinMessage.h @@ -85,8 +85,9 @@ class DLL_EXPORT CheckinMessage * CHIP_ERROR_BUFFER_TOO_SMALL if appData buffer is too small * CHIP_ERROR_INTERNAL if we were not able to decrypt or validate the Check-In message */ + static CHIP_ERROR ParseCheckinMessagePayload(const Crypto::Aes128KeyHandle & aes128KeyHandle, - const Crypto::Hmac128KeyHandle & hmacKeyHandle, ByteSpan & payload, + const Crypto::Hmac128KeyHandle & hmacKeyHandle, const ByteSpan & payload, CounterType & counter, MutableByteSpan & appData); static inline size_t GetCheckinPayloadSize(size_t appDataSize) { return appDataSize + kMinPayloadSize; } @@ -97,7 +98,7 @@ class DLL_EXPORT CheckinMessage * @param payload The undecrypted payload * @return size_t size in byte of the application data from the payload */ - static size_t GetAppDataSize(ByteSpan & payload); + static size_t GetAppDataSize(const ByteSpan & payload); static constexpr uint16_t kMinPayloadSize = CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES + sizeof(CounterType) + CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES;