diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index ed0e2a878fc9c2..e83c150a632196 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -263,6 +263,57 @@ FabricInfo * RetrieveCurrentFabric(CommandHandler * aCommandHandler) return Server::GetInstance().GetFabricTable().FindFabricWithIndex(index); } +void FailSafeCleanup(const chip::DeviceLayer::ChipDeviceEvent * event) +{ + emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: Call to FailSafeCleanup"); + + FabricIndex fabricIndex = event->CommissioningComplete.PeerFabricIndex; + + // If an AddNOC or UpdateNOC command has been successfully invoked, terminate all CASE sessions associated with the Fabric + // whose Fabric Index is recorded in the Fail-Safe context (see ArmFailSafe Command) by clearing any associated Secure + // Session Context at the Server. + if (event->CommissioningComplete.AddNocCommandHasBeenInvoked || event->CommissioningComplete.UpdateNocCommandHasBeenInvoked) + { + CASESessionManager * caseSessionManager = Server::GetInstance().GetCASESessionManager(); + if (caseSessionManager) + { + FabricInfo * fabricInfo = Server::GetInstance().GetFabricTable().FindFabricWithIndex(fabricIndex); + VerifyOrReturn(fabricInfo != nullptr); + + caseSessionManager->ReleaseSessionsForFabric(fabricInfo->GetCompressedId()); + } + + Server::GetInstance().GetSecureSessionManager().ExpireAllPairingsForFabric(fabricIndex); + } + + // If an AddNOC command had been successfully invoked, achieve the equivalent effect of invoking the RemoveFabric command + // against the Fabric Index stored in the Fail-Safe Context for the Fabric Index that was the subject of the AddNOC + // command. + if (event->CommissioningComplete.AddNocCommandHasBeenInvoked) + { + Server::GetInstance().GetFabricTable().Delete(fabricIndex); + } + + // If an UpdateNOC command had been successfully invoked, revert the state of operational key pair, NOC and ICAC for that + // Fabric to the state prior to the Fail-Safe timer being armed, for the Fabric Index that was the subject of the UpdateNOC + // command. + if (event->CommissioningComplete.UpdateNocCommandHasBeenInvoked) + { + // TODO: Revert the state of operational key pair, NOC and ICAC + } +} + +void OnPlatformEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +{ + if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete) + { + if (event->CommissioningComplete.Status != CHIP_NO_ERROR) + { + FailSafeCleanup(event); + } + } +} + } // anonymous namespace // As per specifications section 11.22.5.1. Constant RESP_MAX @@ -341,6 +392,8 @@ void MatterOperationalCredentialsPluginServerInitCallback(void) registerAttributeAccessOverride(&gAttrAccess); Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); + + DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler); } namespace { @@ -599,7 +652,7 @@ bool emberAfOperationalCredentialsClusterAddNOCCallback(app::CommandHandler * co // The Fabric Index associated with the armed fail-safe context SHALL be updated to match the Fabric // Index just allocated. - failSafeContext.SetNocCommandInvoked(fabricIndex); + failSafeContext.SetAddNocCommandInvoked(fabricIndex); exit: @@ -666,7 +719,7 @@ bool emberAfOperationalCredentialsClusterUpdateNOCCallback(app::CommandHandler * // The Fabric Index associated with the armed fail-safe context SHALL be updated to match the Fabric // Index associated with the UpdateNOC command being invoked. - failSafeContext.SetNocCommandInvoked(fabricIndex); + failSafeContext.SetUpdateNocCommandInvoked(fabricIndex); exit: diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index b6431bc8b22e33..3a043d12ba61cc 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -444,6 +444,8 @@ struct ChipDeviceEvent final CHIP_ERROR Status; uint64_t PeerNodeId; FabricIndex PeerFabricIndex; + bool AddNocCommandHasBeenInvoked; + bool UpdateNocCommandHasBeenInvoked; } CommissioningComplete; struct diff --git a/src/include/platform/FailSafeContext.h b/src/include/platform/FailSafeContext.h index 41eaac12023c07..e31af9bf43e9e2 100644 --- a/src/include/platform/FailSafeContext.h +++ b/src/include/platform/FailSafeContext.h @@ -55,12 +55,20 @@ class FailSafeContext return (accessingFabricIndex == mFabricIndex); } - inline bool NocCommandHasBeenInvoked() const { return mNocCommandHasBeenInvoked; } + inline bool NocCommandHasBeenInvoked() const { return mAddNocCommandHasBeenInvoked || mUpdateNocCommandHasBeenInvoked; } + inline bool AddNocCommandHasBeenInvoked() { return mAddNocCommandHasBeenInvoked; } + inline bool UpdateNocCommandHasBeenInvoked() { return mUpdateNocCommandHasBeenInvoked; } - inline void SetNocCommandInvoked(FabricIndex nocFabricIndex) + inline void SetAddNocCommandInvoked(FabricIndex nocFabricIndex) { - mNocCommandHasBeenInvoked = true; - mFabricIndex = nocFabricIndex; + mAddNocCommandHasBeenInvoked = true; + mFabricIndex = nocFabricIndex; + } + + inline void SetUpdateNocCommandInvoked(FabricIndex nocFabricIndex) + { + mUpdateNocCommandHasBeenInvoked = true; + mFabricIndex = nocFabricIndex; } inline FabricIndex GetFabricIndex() const @@ -72,9 +80,10 @@ class FailSafeContext private: // ===== Private members reserved for use by this class only. - bool mFailSafeArmed = false; - bool mNocCommandHasBeenInvoked = false; - FabricIndex mFabricIndex = kUndefinedFabricIndex; + bool mFailSafeArmed = false; + bool mAddNocCommandHasBeenInvoked = false; + bool mUpdateNocCommandHasBeenInvoked = false; + FabricIndex mFabricIndex = kUndefinedFabricIndex; // TODO:: Track the state of what was mutated during fail-safe. diff --git a/src/platform/DeviceControlServer.cpp b/src/platform/DeviceControlServer.cpp index eb9bc6731c2c9d..1582f9e4f47ddf 100644 --- a/src/platform/DeviceControlServer.cpp +++ b/src/platform/DeviceControlServer.cpp @@ -37,11 +37,16 @@ DeviceControlServer & DeviceControlServer::DeviceControlSvr() CHIP_ERROR DeviceControlServer::CommissioningComplete(NodeId peerNodeId, FabricIndex accessingFabricIndex) { VerifyOrReturnError(CHIP_NO_ERROR == mFailSafeContext.DisarmFailSafe(), CHIP_ERROR_INTERNAL); + ChipDeviceEvent event; - event.Type = DeviceEventType::kCommissioningComplete; - event.CommissioningComplete.PeerNodeId = peerNodeId; - event.CommissioningComplete.PeerFabricIndex = accessingFabricIndex; - event.CommissioningComplete.Status = CHIP_NO_ERROR; + + event.Type = DeviceEventType::kCommissioningComplete; + event.CommissioningComplete.PeerNodeId = peerNodeId; + event.CommissioningComplete.PeerFabricIndex = accessingFabricIndex; + event.CommissioningComplete.AddNocCommandHasBeenInvoked = mFailSafeContext.AddNocCommandHasBeenInvoked(); + event.CommissioningComplete.UpdateNocCommandHasBeenInvoked = mFailSafeContext.UpdateNocCommandHasBeenInvoked(); + event.CommissioningComplete.Status = CHIP_NO_ERROR; + return PlatformMgr().PostEvent(&event); } diff --git a/src/platform/FailSafeContext.cpp b/src/platform/FailSafeContext.cpp index 0a732fd8b194d4..14e0bb417db72f 100644 --- a/src/platform/FailSafeContext.cpp +++ b/src/platform/FailSafeContext.cpp @@ -35,16 +35,17 @@ void FailSafeContext::HandleArmFailSafe(System::Layer * layer, void * aAppState) void FailSafeContext::CommissioningFailedTimerComplete() { - // TODO: If the fail-safe timer expires before the CommissioningComplete command is - // successfully invoked, conduct clean-up steps. - ChipDeviceEvent event; - event.Type = DeviceEventType::kCommissioningComplete; - event.CommissioningComplete.Status = CHIP_ERROR_TIMEOUT; - CHIP_ERROR status = PlatformMgr().PostEvent(&event); + event.Type = DeviceEventType::kCommissioningComplete; + event.CommissioningComplete.PeerFabricIndex = mFabricIndex; + event.CommissioningComplete.AddNocCommandHasBeenInvoked = mAddNocCommandHasBeenInvoked; + event.CommissioningComplete.UpdateNocCommandHasBeenInvoked = mUpdateNocCommandHasBeenInvoked; + event.CommissioningComplete.Status = CHIP_ERROR_TIMEOUT; + CHIP_ERROR status = PlatformMgr().PostEvent(&event); - mFailSafeArmed = false; - mNocCommandHasBeenInvoked = false; + mFailSafeArmed = false; + mAddNocCommandHasBeenInvoked = false; + mUpdateNocCommandHasBeenInvoked = false; if (status != CHIP_NO_ERROR) { @@ -62,8 +63,9 @@ CHIP_ERROR FailSafeContext::ArmFailSafe(FabricIndex accessingFabricIndex, System CHIP_ERROR FailSafeContext::DisarmFailSafe() { - mFailSafeArmed = false; - mNocCommandHasBeenInvoked = false; + mFailSafeArmed = false; + mAddNocCommandHasBeenInvoked = false; + mUpdateNocCommandHasBeenInvoked = false; DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafe, this); return CHIP_NO_ERROR; }