Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup OperationalCredentials if the fail-safe timer expires #16212

Merged
merged 4 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,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());
yufengwangca marked this conversation as resolved.
Show resolved Hide resolved
}

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
Expand Down Expand Up @@ -340,6 +391,8 @@ void MatterOperationalCredentialsPluginServerInitCallback(void)
registerAttributeAccessOverride(&gAttrAccess);

Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate);

DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler);
}

namespace {
Expand Down Expand Up @@ -595,7 +648,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:

Expand Down Expand Up @@ -661,7 +714,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:

Expand Down
2 changes: 2 additions & 0 deletions src/include/platform/CHIPDeviceEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ struct ChipDeviceEvent final
CHIP_ERROR Status;
uint64_t PeerNodeId;
FabricIndex PeerFabricIndex;
bool AddNocCommandHasBeenInvoked;
bool UpdateNocCommandHasBeenInvoked;
} CommissioningComplete;

struct
Expand Down
23 changes: 16 additions & 7 deletions src/include/platform/FailSafeContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
yufengwangca marked this conversation as resolved.
Show resolved Hide resolved
mFabricIndex = nocFabricIndex;
}

inline void SetUpdateNocCommandInvoked(FabricIndex nocFabricIndex)
{
mUpdateNocCommandHasBeenInvoked = true;
mFabricIndex = nocFabricIndex;
}
yufengwangca marked this conversation as resolved.
Show resolved Hide resolved

inline FabricIndex GetFabricIndex() const
Expand All @@ -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.

Expand Down
13 changes: 9 additions & 4 deletions src/platform/DeviceControlServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
22 changes: 12 additions & 10 deletions src/platform/FailSafeContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
yufengwangca marked this conversation as resolved.
Show resolved Hide resolved
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)
{
Expand All @@ -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;
}
Expand Down