Fix multiple check-in/peer nodeId handling in icd client side (#35304)

diff --git a/examples/chip-tool/commands/clusters/ClusterCommand.h b/examples/chip-tool/commands/clusters/ClusterCommand.h
index bf5c61f..ad77b54 100644
--- a/examples/chip-tool/commands/clusters/ClusterCommand.h
+++ b/examples/chip-tool/commands/clusters/ClusterCommand.h
@@ -60,7 +60,7 @@
                            const chip::app::Clusters::IcdManagement::Commands::UnregisterClient::Type & value)
     {
         ReturnErrorOnFailure(InteractionModelCommands::SendCommand(device, endpointId, clusterId, commandId, value));
-        mScopedNodeId = chip::ScopedNodeId(value.checkInNodeID, device->GetSecureSession().Value()->GetFabricIndex());
+        mPeerNodeId = chip::ScopedNodeId(device->GetDeviceId(), device->GetSecureSession().Value()->GetFabricIndex());
         return CHIP_NO_ERROR;
     }
 
@@ -69,7 +69,8 @@
                            const chip::app::Clusters::IcdManagement::Commands::RegisterClient::Type & value)
     {
         ReturnErrorOnFailure(InteractionModelCommands::SendCommand(device, endpointId, clusterId, commandId, value));
-        mScopedNodeId     = chip::ScopedNodeId(value.checkInNodeID, device->GetSecureSession().Value()->GetFabricIndex());
+        mPeerNodeId       = chip::ScopedNodeId(device->GetDeviceId(), device->GetSecureSession().Value()->GetFabricIndex());
+        mCheckInNodeId    = chip::ScopedNodeId(value.checkInNodeID, device->GetSecureSession().Value()->GetFabricIndex());
         mMonitoredSubject = value.monitoredSubject;
         mClientType       = value.clientType;
         memcpy(mICDSymmetricKey, value.key.data(), value.key.size());
@@ -147,7 +148,9 @@
                     return;
                 }
                 chip::app::ICDClientInfo clientInfo;
-                clientInfo.peer_node         = mScopedNodeId;
+
+                clientInfo.peer_node         = mPeerNodeId;
+                clientInfo.check_in_node     = mCheckInNodeId;
                 clientInfo.monitored_subject = mMonitoredSubject;
                 clientInfo.start_icd_counter = value.ICDCounter;
                 clientInfo.client_type       = mClientType;
@@ -159,7 +162,7 @@
         if ((path.mEndpointId == chip::kRootEndpointId) && (path.mClusterId == chip::app::Clusters::IcdManagement::Id) &&
             (path.mCommandId == chip::app::Clusters::IcdManagement::Commands::UnregisterClient::Id))
         {
-            ClearICDEntry(mScopedNodeId);
+            ClearICDEntry(mPeerNodeId);
         }
     }
 
@@ -260,9 +263,21 @@
 private:
     chip::ClusterId mClusterId;
     chip::CommandId mCommandId;
-    chip::ScopedNodeId mScopedNodeId;
-    uint64_t mMonitoredSubject                                     = static_cast<uint64_t>(0);
+    // The scoped node ID to which RegisterClient and UnregisterClient command will be sent.  Not set for other commands.
+    chip::ScopedNodeId mPeerNodeId;
+    // The scoped node ID to which a Check-In message will be sent.  Only set for the RegisterClient command.
+    chip::ScopedNodeId mCheckInNodeId;
+
+    // Used to determine if a particular client has an active subscription for the given entry.
+    // The MonitoredSubject, when it is a NodeID, MAY be the same as the CheckInNodeID.
+    // The MonitoredSubject gives the registering client the flexibility of having a different
+    // CheckInNodeID from the MonitoredSubject.
+    uint64_t mMonitoredSubject = static_cast<uint64_t>(0);
+
+    // Client type of the client registering
     chip::app::Clusters::IcdManagement::ClientTypeEnum mClientType = chip::app::Clusters::IcdManagement::ClientTypeEnum::kPermanent;
+
+    // Shared secret between the client and the ICD to encrypt the Check-In message.
     uint8_t mICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length];
 
     CHIP_ERROR mError = CHIP_NO_ERROR;
diff --git a/examples/chip-tool/commands/icd/ICDCommand.cpp b/examples/chip-tool/commands/icd/ICDCommand.cpp
index 3f7bfb3..a66192e 100644
--- a/examples/chip-tool/commands/icd/ICDCommand.cpp
+++ b/examples/chip-tool/commands/icd/ICDCommand.cpp
@@ -40,14 +40,17 @@
     fprintf(stderr, "  +------------------------------------------------------------------------------------------+\n");
     fprintf(stderr, "  | %-88s |\n", "Known ICDs:");
     fprintf(stderr, "  +------------------------------------------------------------------------------------------+\n");
-    fprintf(stderr, "  | %20s | %15s | %15s | %16s | %10s |\n", "Fabric Index:Node ID", "Start Counter", "Counter Offset",
-            "MonitoredSubject", "ClientType");
+    fprintf(stderr, "  | %20s | %20s | %15s | %15s | %16s | %10s |\n", "Fabric Index:Peer Node ID", "Fabric Index:CheckIn Node ID",
+            "Start Counter", "Counter Offset", "MonitoredSubject", "ClientType");
 
     while (iter->Next(info))
     {
         fprintf(stderr, "  +------------------------------------------------------------------------------------------+\n");
-        fprintf(stderr, "  | %3" PRIu32 ":" ChipLogFormatX64 " | %15" PRIu32 " | %15" PRIu32 " | " ChipLogFormatX64 " | %10u |\n",
+        fprintf(stderr,
+                "  | %3" PRIu32 ":" ChipLogFormatX64 " | %3" PRIu32 ":" ChipLogFormatX64 " | %15" PRIu32 " | %15" PRIu32
+                " | " ChipLogFormatX64 " | %10u |\n",
                 static_cast<uint32_t>(info.peer_node.GetFabricIndex()), ChipLogValueX64(info.peer_node.GetNodeId()),
+                static_cast<uint32_t>(info.check_in_node.GetFabricIndex()), ChipLogValueX64(info.check_in_node.GetNodeId()),
                 info.start_icd_counter, info.offset, ChipLogValueX64(info.monitored_subject),
                 static_cast<uint8_t>(info.client_type));
 
diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp
index 245c9ed..b9034cc 100644
--- a/examples/chip-tool/commands/pairing/PairingCommand.cpp
+++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp
@@ -469,7 +469,8 @@
                                sizeof(icdSymmetricKeyHex), chip::Encoding::HexFlags::kNullTerminate);
 
     app::ICDClientInfo clientInfo;
-    clientInfo.peer_node         = chip::ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex());
+    clientInfo.check_in_node     = chip::ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex());
+    clientInfo.peer_node         = nodeId;
     clientInfo.monitored_subject = mICDMonitoredSubject.Value();
     clientInfo.start_icd_counter = icdCounter;
 
diff --git a/src/app/icd/client/DefaultICDClientStorage.cpp b/src/app/icd/client/DefaultICDClientStorage.cpp
index 7582e8f..2b6b3a1 100644
--- a/src/app/icd/client/DefaultICDClientStorage.cpp
+++ b/src/app/icd/client/DefaultICDClientStorage.cpp
@@ -235,16 +235,22 @@
         ICDClientInfo clientInfo;
         TLV::TLVType ICDClientInfoType;
         NodeId nodeId;
+        NodeId checkInNodeId;
         FabricIndex fabric;
         ReturnErrorOnFailure(reader.EnterContainer(ICDClientInfoType));
         // Peer Node ID
         ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kPeerNodeId)));
         ReturnErrorOnFailure(reader.Get(nodeId));
 
+        ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kCheckInNodeId)));
+        ReturnErrorOnFailure(reader.Get(checkInNodeId));
+
         // Fabric Index
         ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kFabricIndex)));
         ReturnErrorOnFailure(reader.Get(fabric));
-        clientInfo.peer_node = ScopedNodeId(nodeId, fabric);
+
+        clientInfo.peer_node     = ScopedNodeId(nodeId, fabric);
+        clientInfo.check_in_node = ScopedNodeId(checkInNodeId, fabric);
 
         // Start ICD Counter
         ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kStartICDCounter)));
@@ -323,6 +329,7 @@
         TLV::TLVType ICDClientInfoContainerType;
         ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, ICDClientInfoContainerType));
         ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kPeerNodeId), clientInfo.peer_node.GetNodeId()));
+        ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kCheckInNodeId), clientInfo.check_in_node.GetNodeId()));
         ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kFabricIndex), clientInfo.peer_node.GetFabricIndex()));
         ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kStartICDCounter), clientInfo.start_icd_counter));
         ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kOffset), clientInfo.offset));
diff --git a/src/app/icd/client/DefaultICDClientStorage.h b/src/app/icd/client/DefaultICDClientStorage.h
index c3c4560..76faeb9 100644
--- a/src/app/icd/client/DefaultICDClientStorage.h
+++ b/src/app/icd/client/DefaultICDClientStorage.h
@@ -124,13 +124,14 @@
     enum class ClientInfoTag : uint8_t
     {
         kPeerNodeId       = 1,
-        kFabricIndex      = 2,
-        kStartICDCounter  = 3,
-        kOffset           = 4,
-        kMonitoredSubject = 5,
-        kAesKeyHandle     = 6,
-        kHmacKeyHandle    = 7,
-        kClientType       = 8,
+        kCheckInNodeId    = 2,
+        kFabricIndex      = 3,
+        kStartICDCounter  = 4,
+        kOffset           = 5,
+        kMonitoredSubject = 6,
+        kAesKeyHandle     = 7,
+        kHmacKeyHandle    = 8,
+        kClientType       = 9,
     };
 
     enum class CounterTag : uint8_t
@@ -158,8 +159,9 @@
     {
         // All the fields added together
         return TLV::EstimateStructOverhead(
-            sizeof(NodeId), sizeof(FabricIndex), sizeof(uint32_t) /*start_icd_counter*/, sizeof(uint32_t) /*offset*/,
-            sizeof(uint64_t) /*monitored_subject*/, sizeof(Crypto::Symmetric128BitsKeyByteArray) /*aes_key_handle*/,
+            sizeof(NodeId), sizeof(NodeId), sizeof(FabricIndex), sizeof(uint32_t) /*start_icd_counter*/,
+            sizeof(uint32_t) /*offset*/, sizeof(uint64_t) /*monitored_subject*/,
+            sizeof(Crypto::Symmetric128BitsKeyByteArray) /*aes_key_handle*/,
             sizeof(Crypto::Symmetric128BitsKeyByteArray) /*hmac_key_handle*/, sizeof(uint8_t) /*client_type*/);
     }
 
diff --git a/src/app/icd/client/ICDClientInfo.h b/src/app/icd/client/ICDClientInfo.h
index 45aabf2..4959524 100644
--- a/src/app/icd/client/ICDClientInfo.h
+++ b/src/app/icd/client/ICDClientInfo.h
@@ -31,6 +31,7 @@
 struct ICDClientInfo
 {
     ScopedNodeId peer_node;
+    ScopedNodeId check_in_node;
     uint32_t start_icd_counter                          = 0;
     uint32_t offset                                     = 0;
     Clusters::IcdManagement::ClientTypeEnum client_type = Clusters::IcdManagement::ClientTypeEnum::kPermanent;
@@ -44,6 +45,7 @@
     ICDClientInfo & operator=(const ICDClientInfo & other)
     {
         peer_node         = other.peer_node;
+        check_in_node     = other.check_in_node;
         start_icd_counter = other.start_icd_counter;
         offset            = other.offset;
         client_type       = other.client_type;
diff --git a/src/app/icd/client/RefreshKeySender.cpp b/src/app/icd/client/RefreshKeySender.cpp
index 36456b0..8b6122d 100644
--- a/src/app/icd/client/RefreshKeySender.cpp
+++ b/src/app/icd/client/RefreshKeySender.cpp
@@ -77,7 +77,7 @@
     EndpointId endpointId = 0;
 
     Clusters::IcdManagement::Commands::RegisterClient::Type registerClientCommand;
-    registerClientCommand.checkInNodeID    = mICDClientInfo.peer_node.GetNodeId();
+    registerClientCommand.checkInNodeID    = mICDClientInfo.check_in_node.GetNodeId();
     registerClientCommand.monitoredSubject = mICDClientInfo.monitored_subject;
     registerClientCommand.key              = mNewKey.Span();
     return Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, registerClientCommand, onSuccess, onFailure);
diff --git a/src/controller/java/AndroidCheckInDelegate.cpp b/src/controller/java/AndroidCheckInDelegate.cpp
index 1091738..ab28ea0 100644
--- a/src/controller/java/AndroidCheckInDelegate.cpp
+++ b/src/controller/java/AndroidCheckInDelegate.cpp
@@ -23,8 +23,10 @@
 #include <lib/support/JniReferences.h>
 #include <lib/support/logging/CHIPLogging.h>
 
-#define PARSE_CLIENT_INFO(_clientInfo, _peerNodeId, _startCounter, _offset, _monitoredSubject, _jniICDAesKey, _jniICDHmacKey)      \
+#define PARSE_CLIENT_INFO(_clientInfo, _peerNodeId, _checkInNodeId, _startCounter, _offset, _monitoredSubject, _jniICDAesKey,      \
+                          _jniICDHmacKey)                                                                                          \
     jlong _peerNodeId       = static_cast<jlong>(_clientInfo.peer_node.GetNodeId());                                               \
+    jlong _checkInNodeId    = static_cast<jlong>(_clientInfo.check_in_node.GetNodeId());                                           \
     jlong _startCounter     = static_cast<jlong>(_clientInfo.start_icd_counter);                                                   \
     jlong _offset           = static_cast<jlong>(_clientInfo.offset);                                                              \
     jlong _monitoredSubject = static_cast<jlong>(_clientInfo.monitored_subject);                                                   \
@@ -53,24 +55,26 @@
 
 void AndroidCheckInDelegate::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));
+    ChipLogProgress(ICD,
+                    "Check In Message processing complete: start_counter=%" PRIu32 " offset=%" PRIu32
+                    " peernodeid=" ChipLogFormatScopedNodeId " checkinnodeid=" ChipLogFormatScopedNodeId,
+                    clientInfo.start_icd_counter, clientInfo.offset, ChipLogValueScopedNodeId(clientInfo.peer_node),
+                    ChipLogValueScopedNodeId(clientInfo.check_in_node));
 
     VerifyOrReturn(mCheckInDelegate.HasValidObjectRef(), ChipLogProgress(ICD, "check-in delegate is not implemented!"));
 
     JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
     VerifyOrReturn(env != nullptr, ChipLogError(Controller, "JNIEnv is null!"));
-    PARSE_CLIENT_INFO(clientInfo, peerNodeId, startCounter, offset, monitoredSubject, jniICDAesKey, jniICDHmacKey)
+    PARSE_CLIENT_INFO(clientInfo, peerNodeId, checkInNodeId, startCounter, offset, monitoredSubject, jniICDAesKey, jniICDHmacKey)
 
     jmethodID onCheckInCompleteMethodID = nullptr;
     CHIP_ERROR err = chip::JniReferences::GetInstance().FindMethod(env, mCheckInDelegate.ObjectRef(), "onCheckInComplete",
-                                                                   "(JJJJ[B[B)V", &onCheckInCompleteMethodID);
+                                                                   "(JJJJJ[B[B)V", &onCheckInCompleteMethodID);
     VerifyOrReturn(err == CHIP_NO_ERROR,
                    ChipLogProgress(ICD, "onCheckInComplete - FindMethod is failed! : %" CHIP_ERROR_FORMAT, err.Format()));
 
-    env->CallVoidMethod(mCheckInDelegate.ObjectRef(), onCheckInCompleteMethodID, peerNodeId, startCounter, offset, monitoredSubject,
-                        jniICDAesKey.jniValue(), jniICDHmacKey.jniValue());
+    env->CallVoidMethod(mCheckInDelegate.ObjectRef(), onCheckInCompleteMethodID, peerNodeId, checkInNodeId, startCounter, offset,
+                        monitoredSubject, jniICDAesKey.jniValue(), jniICDHmacKey.jniValue());
 }
 
 RefreshKeySender * AndroidCheckInDelegate::OnKeyRefreshNeeded(ICDClientInfo & clientInfo, ICDClientStorage * clientStorage)
@@ -84,17 +88,18 @@
         JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
         VerifyOrReturnValue(env != nullptr, nullptr, ChipLogError(Controller, "JNIEnv is null!"));
 
-        PARSE_CLIENT_INFO(clientInfo, peerNodeId, startCounter, offset, monitoredSubject, jniICDAesKey, jniICDHmacKey)
+        PARSE_CLIENT_INFO(clientInfo, peerNodeId, checkInNodeId, startCounter, offset, monitoredSubject, jniICDAesKey,
+                          jniICDHmacKey)
 
         jmethodID onKeyRefreshNeededMethodID = nullptr;
-        err = chip::JniReferences::GetInstance().FindMethod(env, mCheckInDelegate.ObjectRef(), "onKeyRefreshNeeded", "(JJJJ[B[B)V",
+        err = chip::JniReferences::GetInstance().FindMethod(env, mCheckInDelegate.ObjectRef(), "onKeyRefreshNeeded", "(JJJJJ[B[B)V",
                                                             &onKeyRefreshNeededMethodID);
         VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                             ChipLogProgress(ICD, "onKeyRefreshNeeded - FindMethod is failed! : %" CHIP_ERROR_FORMAT, err.Format()));
 
-        jbyteArray key = static_cast<jbyteArray>(env->CallObjectMethod(mCheckInDelegate.ObjectRef(), onKeyRefreshNeededMethodID,
-                                                                       peerNodeId, startCounter, offset, monitoredSubject,
-                                                                       jniICDAesKey.jniValue(), jniICDHmacKey.jniValue()));
+        jbyteArray key = static_cast<jbyteArray>(
+            env->CallObjectMethod(mCheckInDelegate.ObjectRef(), onKeyRefreshNeededMethodID, peerNodeId, checkInNodeId, startCounter,
+                                  offset, monitoredSubject, jniICDAesKey.jniValue(), jniICDHmacKey.jniValue()));
 
         if (key != nullptr)
         {
diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp
index af5d220..f634f8a 100644
--- a/src/controller/java/AndroidDeviceControllerWrapper.cpp
+++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp
@@ -1015,6 +1015,8 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::app::ICDClientInfo clientInfo;
     clientInfo.peer_node         = icdNodeId;
+    clientInfo.check_in_node     = chip::ScopedNodeId(mAutoCommissioner.GetCommissioningParameters().GetICDCheckInNodeId().Value(),
+                                                      icdNodeId.GetFabricIndex());
     clientInfo.monitored_subject = mAutoCommissioner.GetCommissioningParameters().GetICDMonitoredSubject().Value();
     clientInfo.start_icd_counter = icdCounter;
 
@@ -1056,7 +1058,7 @@
     methodErr = chip::JniReferences::GetInstance().GetLocalClassRef(env, "chip/devicecontroller/ICDDeviceInfo", icdDeviceInfoClass);
     VerifyOrReturn(methodErr == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find class ICDDeviceInfo"));
 
-    icdDeviceInfoStructCtor = env->GetMethodID(icdDeviceInfoClass, "<init>", "([BILjava/lang/String;JJIJJJJI)V");
+    icdDeviceInfoStructCtor = env->GetMethodID(icdDeviceInfoClass, "<init>", "([BILjava/lang/String;JJIJJJJJI)V");
     VerifyOrReturn(icdDeviceInfoStructCtor != nullptr, ChipLogError(Controller, "Could not find ICDDeviceInfo constructor"));
 
     methodErr =
@@ -1069,7 +1071,9 @@
     icdDeviceInfoObj = env->NewObject(
         icdDeviceInfoClass, icdDeviceInfoStructCtor, jSymmetricKey, static_cast<jint>(mUserActiveModeTriggerHint.Raw()),
         jUserActiveModeTriggerInstruction, static_cast<jlong>(mIdleModeDuration), static_cast<jlong>(mActiveModeDuration),
-        static_cast<jint>(mActiveModeThreshold), static_cast<jlong>(icdNodeId.GetNodeId()), static_cast<jlong>(icdCounter),
+        static_cast<jint>(mActiveModeThreshold), static_cast<jlong>(icdNodeId.GetNodeId()),
+        static_cast<jlong>(mAutoCommissioner.GetCommissioningParameters().GetICDCheckInNodeId().Value()),
+        static_cast<jlong>(icdCounter),
         static_cast<jlong>(mAutoCommissioner.GetCommissioningParameters().GetICDMonitoredSubject().Value()),
         static_cast<jlong>(Controller()->GetFabricId()), static_cast<jint>(Controller()->GetFabricIndex()));
 
diff --git a/src/controller/java/AndroidICDClient.cpp b/src/controller/java/AndroidICDClient.cpp
index 036d92b..867a55d 100644
--- a/src/controller/java/AndroidICDClient.cpp
+++ b/src/controller/java/AndroidICDClient.cpp
@@ -58,7 +58,7 @@
                         ChipLogError(Controller, "Find ICDClientInfo class: %" CHIP_ERROR_FORMAT, err.Format()));
 
     env->ExceptionClear();
-    constructor = env->GetMethodID(infoClass, "<init>", "(JJJJ[B[B)V");
+    constructor = env->GetMethodID(infoClass, "<init>", "(JJJJJ[B[B)V");
     VerifyOrReturnValue(constructor != nullptr, nullptr, ChipLogError(Controller, "Find GetMethodID error!"));
 
     while (iter->Next(info))
@@ -84,9 +84,10 @@
         VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
                             ChipLogError(Controller, "ICD HMAC KEY N2J_ByteArray error!: %" CHIP_ERROR_FORMAT, err.Format()));
 
-        jICDClientInfo = (jobject) env->NewObject(infoClass, constructor, static_cast<jlong>(info.peer_node.GetNodeId()),
-                                                  static_cast<jlong>(info.start_icd_counter), static_cast<jlong>(info.offset),
-                                                  static_cast<jlong>(info.monitored_subject), jIcdAesKey, jIcdHmacKey);
+        jICDClientInfo = static_cast<jobject>(
+            env->NewObject(infoClass, constructor, static_cast<jlong>(info.peer_node.GetNodeId()),
+                           static_cast<jlong>(info.check_in_node.GetNodeId()), static_cast<jlong>(info.start_icd_counter),
+                           static_cast<jlong>(info.offset), static_cast<jlong>(info.monitored_subject), jIcdAesKey, jIcdHmacKey));
 
         err = chip::JniReferences::GetInstance().AddToList(jInfo, jICDClientInfo);
         VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr,
@@ -154,6 +155,7 @@
     VerifyOrReturnError(jIcdClientInfo != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
 
     jmethodID getPeerNodeIdMethod       = nullptr;
+    jmethodID getCheckInNodeIdMethod    = nullptr;
     jmethodID getStartCounterMethod     = nullptr;
     jmethodID getOffsetMethod           = nullptr;
     jmethodID getMonitoredSubjectMethod = nullptr;
@@ -163,6 +165,8 @@
     ReturnErrorOnFailure(
         chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getPeerNodeId", "()J", &getPeerNodeIdMethod));
     ReturnErrorOnFailure(
+        chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getCheckInNodeId", "()J", &getCheckInNodeIdMethod));
+    ReturnErrorOnFailure(
         chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getStartCounter", "()J", &getStartCounterMethod));
     ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getOffset", "()J", &getOffsetMethod));
     ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getMonitoredSubject", "()J",
@@ -173,17 +177,20 @@
         chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getIcdHmacKey", "()[B", &getIcdHmacKeyMethod));
 
     jlong jPeerNodeId       = env->CallLongMethod(jIcdClientInfo, getPeerNodeIdMethod);
+    jlong jCheckInNodeId    = env->CallLongMethod(jIcdClientInfo, getCheckInNodeIdMethod);
     jlong jStartCounter     = env->CallLongMethod(jIcdClientInfo, getStartCounterMethod);
     jlong jOffset           = env->CallLongMethod(jIcdClientInfo, getOffsetMethod);
     jlong jMonitoredSubject = env->CallLongMethod(jIcdClientInfo, getMonitoredSubjectMethod);
     jbyteArray jIcdAesKey   = static_cast<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdAesKeyMethod));
     jbyteArray jIcdHmacKey  = static_cast<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdHmacKeyMethod));
 
-    chip::ScopedNodeId scopedNodeId(static_cast<chip::NodeId>(jPeerNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
+    chip::ScopedNodeId peerNodeId(static_cast<chip::NodeId>(jPeerNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
+    chip::ScopedNodeId checkInNodeId(static_cast<chip::NodeId>(jCheckInNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
     chip::JniByteArray jniIcdAesKey(env, jIcdAesKey);
     chip::JniByteArray jniIcdHmacKey(env, jIcdHmacKey);
 
-    icdClientInfo.peer_node         = scopedNodeId;
+    icdClientInfo.peer_node         = peerNodeId;
+    icdClientInfo.check_in_node     = checkInNodeId;
     icdClientInfo.start_icd_counter = static_cast<uint32_t>(jStartCounter);
     icdClientInfo.offset            = static_cast<uint32_t>(jOffset);
     icdClientInfo.monitored_subject = static_cast<uint64_t>(jMonitoredSubject);
diff --git a/src/controller/java/src/chip/devicecontroller/ICDCheckInDelegateWrapper.java b/src/controller/java/src/chip/devicecontroller/ICDCheckInDelegateWrapper.java
index 39ca5df..3b33804 100644
--- a/src/controller/java/src/chip/devicecontroller/ICDCheckInDelegateWrapper.java
+++ b/src/controller/java/src/chip/devicecontroller/ICDCheckInDelegateWrapper.java
@@ -29,6 +29,7 @@
   @SuppressWarnings("unused")
   private void onCheckInComplete(
       long peerNodeId,
+      long checkInNodeId,
       long startCounter,
       long offset,
       long monitoredSubject,
@@ -36,12 +37,19 @@
       byte[] icdHmacKey) {
     delegate.onCheckInComplete(
         new ICDClientInfo(
-            peerNodeId, startCounter, offset, monitoredSubject, icdAesKey, icdHmacKey));
+            peerNodeId,
+            checkInNodeId,
+            startCounter,
+            offset,
+            monitoredSubject,
+            icdAesKey,
+            icdHmacKey));
   }
 
   @SuppressWarnings("unused")
   private byte[] onKeyRefreshNeeded(
       long peerNodeId,
+      long checkInNodeId,
       long startCounter,
       long offset,
       long monitoredSubject,
@@ -49,7 +57,13 @@
       byte[] icdHmacKey) {
     return delegate.onKeyRefreshNeeded(
         new ICDClientInfo(
-            peerNodeId, startCounter, offset, monitoredSubject, icdAesKey, icdHmacKey));
+            peerNodeId,
+            checkInNodeId,
+            startCounter,
+            offset,
+            monitoredSubject,
+            icdAesKey,
+            icdHmacKey));
   }
 
   @SuppressWarnings("unused")
diff --git a/src/controller/java/src/chip/devicecontroller/ICDClientInfo.java b/src/controller/java/src/chip/devicecontroller/ICDClientInfo.java
index 77df917..ff028ae 100644
--- a/src/controller/java/src/chip/devicecontroller/ICDClientInfo.java
+++ b/src/controller/java/src/chip/devicecontroller/ICDClientInfo.java
@@ -20,6 +20,7 @@
 /** Class for holding ICD Client information. */
 public class ICDClientInfo {
   private final long peerNodeId;
+  private final long checkInNodeId;
   private final long startCounter;
   private final long offset;
   private final long monitoredSubject;
@@ -28,12 +29,14 @@
 
   public ICDClientInfo(
       long peerNodeId,
+      long checkInNodeId,
       long startCounter,
       long offset,
       long monitoredSubject,
       byte[] icdAesKey,
       byte[] icdHmacKey) {
     this.peerNodeId = peerNodeId;
+    this.checkInNodeId = checkInNodeId;
     this.startCounter = startCounter;
     this.offset = offset;
     this.monitoredSubject = monitoredSubject;
@@ -41,11 +44,16 @@
     this.icdHmacKey = icdHmacKey;
   }
 
-  /** Returns the check in peer node ID. */
+  /** Returns the peer node ID. */
   public long getPeerNodeId() {
     return peerNodeId;
   }
 
+  /** Returns the check in node ID. */
+  public long getCheckInNodeId() {
+    return checkInNodeId;
+  }
+
   /** Returns the Start Counter. */
   public long getStartCounter() {
     return startCounter;
@@ -76,6 +84,8 @@
     return "ICDClientInfo{"
         + "\n\tpeerNodeId="
         + peerNodeId
+        + "\n\tcheckInNodeId="
+        + checkInNodeId
         + "\n\t, startCounter="
         + startCounter
         + "\n\t, offset="
diff --git a/src/controller/java/src/matter/controller/ICDClientInfo.kt b/src/controller/java/src/matter/controller/ICDClientInfo.kt
index 3f0f302..a1c543a 100644
--- a/src/controller/java/src/matter/controller/ICDClientInfo.kt
+++ b/src/controller/java/src/matter/controller/ICDClientInfo.kt
@@ -21,11 +21,12 @@
 /** Class for holding ICD Client information. */
 data class ICDClientInfo(
   val peerNodeId: Long,
+  val checkInNodeId: Long,
   val startCounter: Long,
   val offset: Long,
   val monitoredSubject: Long,
   val icdAesKey: ByteArray,
   val icdHmacKey: ByteArray
 ) {
-  override fun toString(): String = "$peerNodeId/$startCounter/$offset/$monitoredSubject"
+  override fun toString(): String = "$peerNodeId/$checkInNodeId/$startCounter/$offset/$monitoredSubject"
 }
diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp
index c04481a..11dc4bc 100644
--- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp
+++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp
@@ -188,7 +188,8 @@
 void ScriptDevicePairingDelegate::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icdCounter)
 {
     app::ICDClientInfo clientInfo;
-    clientInfo.peer_node         = nodeId;
+    clientInfo.peer_node     = nodeId;
+    clientInfo.check_in_node = chip::ScopedNodeId(sCommissioningParameters.GetICDCheckInNodeId().Value(), nodeId.GetFabricIndex());
     clientInfo.monitored_subject = sCommissioningParameters.GetICDMonitoredSubject().Value();
     clientInfo.start_icd_counter = icdCounter;
     clientInfo.client_type       = sCommissioningParameters.GetICDClientType().Value();