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

Invalidate pending CASESession establishment when Fabric changes #19346

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a5015bf
Add invalidate pending CASESession establishment when Fabric changes
tehampson Jun 7, 2022
a5ebd31
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 8, 2022
211a2a4
Address comment and clean up after merging master
tehampson Jun 8, 2022
a07d4c9
Fix runtime and compile time errors
tehampson Jun 8, 2022
0fbf786
Clean up a couple of TODOs
tehampson Jun 8, 2022
bed2c65
Breakout OnFabricNOCUpdated as a standalone callback
tehampson Jun 9, 2022
c3cbc93
restyle
tehampson Jun 9, 2022
65c6c5f
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 9, 2022
9ff1382
restyle and figuring out unit tests
tehampson Jun 9, 2022
cd19588
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 10, 2022
66474f2
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 10, 2022
5a4d62a
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 13, 2022
03a88f0
Add unit test and fix issue discovered by unit test
tehampson Jun 13, 2022
5c19b8d
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 13, 2022
4ceff6b
Fix formating issue
tehampson Jun 13, 2022
cdb8b10
clean up TestCASESession
tehampson Jun 13, 2022
8e3e076
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 14, 2022
91c5614
Change simulating updating fabric NOC test to run in host tests only
tehampson Jun 14, 2022
ad4d136
Address PR comments
tehampson Jun 15, 2022
5fe85ab
Address PR comments
tehampson Jun 15, 2022
7abbb1a
Merge branch 'master' into invalidate-case-session-upon-fabric-update…
tehampson Jun 16, 2022
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
8 changes: 7 additions & 1 deletion src/app/clusters/bindings/BindingManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ namespace {

class BindingFabricTableDelegate : public chip::FabricTable::Delegate
{
void OnFabricDeletedFromStorage(chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
void OnFabricHasChanged(chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex, bool fabricDeleted) override
{
// TODO We likely want to do the same thing regardless of fabricDeleted. For
// now bailing out early when only update.
if (!fabricDeleted)
{
return;
}
chip::BindingTable & bindingTable = chip::BindingTable::GetInstance();
auto iter = bindingTable.begin();
while (iter != bindingTable.end())
Expand Down
7 changes: 6 additions & 1 deletion src/app/clusters/door-lock-server/door-lock-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ DoorLockServer DoorLockServer::instance;

class DoorLockClusterFabricDelegate : public chip::FabricTable::Delegate
{
void OnFabricDeletedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) override
{
if (!fabricDeleted)
{
return;
}

for (auto endpointId : EnabledEndpointsWithServerCluster(chip::app::Clusters::DoorLock::Id))
{
if (!DoorLockServer::Instance().OnFabricRemoved(endpointId, fabricIndex))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,15 @@ class OpCredsFabricTableDelegate : public chip::FabricTable::Delegate
{

// Gets called when a fabric is deleted from KVS store
void OnFabricDeletedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) override
{
// TODO We likely want to do the same thing regardless of fabricDeleted. For
// now bailing out early when only update.
if (!fabricDeleted)
{
return;
}

ChipLogProgress(Zcl, "OpCreds: Fabric index 0x%x was deleted from fabric storage.", static_cast<unsigned>(fabricIndex));
fabricListChanged();

Expand Down
9 changes: 8 additions & 1 deletion src/app/server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,15 @@ class Server
return CHIP_NO_ERROR;
};

void OnFabricDeletedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) override
{
// TODO We likely want to do the same thing regardless of fabricDeleted. For
// now bailing out early when only update.
if (!fabricDeleted)
{
return;
}

(void) fabricTable;
auto & sessionManager = mServer->GetSecureSessionManager();
sessionManager.FabricRemoved(fabricIndex);
Expand Down
9 changes: 8 additions & 1 deletion src/controller/CHIPDeviceControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,17 @@ class DeviceControllerFactory
return CHIP_NO_ERROR;
};

void OnFabricDeletedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) override
{
(void) fabricTable;

// TODO We likely want to do the same thing regardless of fabricDeleted. For
// now bailing out early when only update.
if (!fabricDeleted)
{
return;
}

tehampson marked this conversation as resolved.
Show resolved Hide resolved
if (mSessionManager != nullptr)
{
mSessionManager->FabricRemoved(fabricIndex);
Expand Down
24 changes: 17 additions & 7 deletions src/credentials/FabricTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,19 @@ CHIP_ERROR FabricTable::AddNewFabric(FabricInfo & newFabric, FabricIndex * outpu
return AddNewFabricInner(newFabric, outputIndex);
}

void FabricTable::NotifyDelegatesOfFabricChange(FabricIndex fabricIndex, bool fabricDeleted)
{
FabricTable::Delegate * delegate = mDelegateListRoot;
while (delegate)
{
// It is possible that delegate will remove itself from the list in OnFabricHasChanged,
// so we grab the next delegate in the list now.
tehampson marked this conversation as resolved.
Show resolved Hide resolved
FabricTable::Delegate * nextDelegate = delegate->next;
delegate->OnFabricHasChanged(*this, fabricIndex, fabricDeleted);
delegate = nextDelegate;
}
}

/*
* A validation policy we can pass into VerifyCredentials to extract the
* latest NotBefore time in the certificate chain without having to load the
Expand Down Expand Up @@ -738,6 +751,8 @@ CHIP_ERROR FabricTable::UpdateFabric(FabricIndex fabricIndex, FabricInfo & newFa
// for CASE and current time is also unknown, the certificate
// validity policy will see this condition and can act appropriately.
mLastKnownGoodTime.UpdateLastKnownGoodChipEpochTime(notBeforeCollector.mLatestNotBefore);

NotifyDelegatesOfFabricChange(fabricIndex, false /* fabricDeleted */);
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -841,16 +856,11 @@ CHIP_ERROR FabricTable::Delete(FabricIndex fabricIndex)
else
{
mFabricCount--;
ChipLogProgress(FabricProvisioning, "Fabric (0x%x) deleted. Calling OnFabricDeletedFromStorage",
ChipLogProgress(FabricProvisioning, "Fabric (0x%x) deleted. Calling OnFabricHasChanged",
static_cast<unsigned>(fabricIndex));
}

FabricTable::Delegate * delegate = mDelegateListRoot;
while (delegate)
{
delegate->OnFabricDeletedFromStorage(*this, fabricIndex);
delegate = delegate->next;
}
NotifyDelegatesOfFabricChange(fabricIndex, true /* fabricDeleted */);
}
return CHIP_NO_ERROR;
}
Expand Down
8 changes: 6 additions & 2 deletions src/credentials/FabricTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,11 @@ class DLL_EXPORT FabricTable
virtual ~Delegate() {}

/**
* Gets called when a fabric is deleted, such as on FabricTable::Delete().
* Gets called when a fabric is changed in a significant way, such as cert being updated or fabric being delete.
tehampson marked this conversation as resolved.
Show resolved Hide resolved
* `fabricDeleted` indicates if the fabric has been deleted in case delegate treats updates differently from
* updates.
**/
virtual void OnFabricDeletedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) = 0;
virtual void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) = 0;
mrjerryjohns marked this conversation as resolved.
Show resolved Hide resolved

/**
* Gets called when a fabric is loaded into Fabric Table from storage, such as
Expand Down Expand Up @@ -498,6 +500,8 @@ class DLL_EXPORT FabricTable

CHIP_ERROR AddNewFabricInner(FabricInfo & fabric, FabricIndex * assignedIndex);

void NotifyDelegatesOfFabricChange(FabricIndex fabricIndex, bool fabricDeleted);

FabricInfo mStates[CHIP_CONFIG_MAX_FABRICS];
PersistentStorageDelegate * mStorage = nullptr;

Expand Down
45 changes: 34 additions & 11 deletions src/protocols/secure_channel/CASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,25 @@ void CASESession::Clear()
mState = State::kInitialized;
Crypto::ClearSecretData(mIPK);

if (mFabricsTable)
{
mFabricsTable->RemoveFabricDelegate(&mFabricDelegate);
}

mLocalNodeId = kUndefinedNodeId;
mPeerNodeId = kUndefinedNodeId;
mFabricsTable = nullptr;
mFabricIndex = kUndefinedFabricIndex;
}

void CASESession::InvalidateIfPendingEstablishment()
{
if (!IsSessionEstablishmentInProgress()) {
return;
}
AbortPendingEstablish(CHIP_ERROR_CANCELLED);
}

CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::CertificateValidityPolicy * policy,
SessionEstablishmentDelegate * delegate)
{
Expand All @@ -172,23 +185,31 @@ CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::Certi
}

CHIP_ERROR
CASESession::ListenForSessionEstablishment(SessionManager & sessionManager, FabricTable * fabrics,
CASESession::ListenForSessionEstablishment(SessionManager & sessionManager, FabricTable * fabricTable,
SessionResumptionStorage * sessionResumptionStorage,
Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate,
Optional<ReliableMessageProtocolConfig> mrpConfig)
{
VerifyOrReturnError(fabrics != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(Init(sessionManager, policy, delegate));

CHIP_ERROR err = CHIP_NO_ERROR;
SuccessOrExit(err = fabricTable->AddFabricDelegate(&mFabricDelegate));
tehampson marked this conversation as resolved.
Show resolved Hide resolved

mRole = CryptoContext::SessionRole::kResponder;
mFabricsTable = fabrics;
mFabricsTable = fabricTable;
mSessionResumptionStorage = sessionResumptionStorage;
mLocalMRPConfig = mrpConfig;

ChipLogDetail(SecureChannel, "Allocated SecureSession (%p) - waiting for Sigma1 msg",
mSecureSessionHolder.Get().Value()->AsSecureSession());

return CHIP_NO_ERROR;
exit:
if (err != CHIP_NO_ERROR)
{
Clear();
}
return err;
}

CHIP_ERROR CASESession::EstablishSession(SessionManager & sessionManager, FabricTable * fabricTable, FabricIndex fabricIndex,
Expand Down Expand Up @@ -219,6 +240,8 @@ CHIP_ERROR CASESession::EstablishSession(SessionManager & sessionManager, Fabric
// been initialized
SuccessOrExit(err);

SuccessOrExit(err = fabricTable->AddFabricDelegate(&mFabricDelegate));

mFabricsTable = fabricTable;
mFabricIndex = fabricIndex;
mSessionResumptionStorage = sessionResumptionStorage;
Expand Down Expand Up @@ -248,12 +271,17 @@ void CASESession::OnResponseTimeout(ExchangeContext * ec)
VerifyOrReturn(mExchangeCtxt == ec, ChipLogError(SecureChannel, "CASESession::OnResponseTimeout exchange doesn't match"));
ChipLogError(SecureChannel, "CASESession timed out while waiting for a response from the peer. Current state was %u",
to_underlying(mState));
AbortPendingEstablish(CHIP_ERROR_TIMEOUT);
}

void CASESession::AbortPendingEstablish(CHIP_ERROR err)
{
// Discard the exchange so that Clear() doesn't try closing it. The
// exchange will handle that.
DiscardExchange();
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(CHIP_ERROR_TIMEOUT);
mDelegate->OnSessionEstablishmentError(err);
}

CHIP_ERROR CASESession::DeriveSecureSession(CryptoContext & session) const
Expand Down Expand Up @@ -1758,12 +1786,7 @@ CHIP_ERROR CASESession::OnMessageReceived(ExchangeContext * ec, const PayloadHea
// Call delegate to indicate session establishment failure.
if (err != CHIP_NO_ERROR)
{
// Discard the exchange so that Clear() doesn't try closing it. The
// exchange will handle that.
DiscardExchange();
Clear();
// Do this last in case the delegate frees us.
mDelegate->OnSessionEstablishmentError(err);
AbortPendingEstablish(err);
}
return err;
}
Expand Down
36 changes: 35 additions & 1 deletion src/protocols/secure_channel/CASESession.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
* @return CHIP_ERROR The result of initialization
*/
CHIP_ERROR ListenForSessionEstablishment(
SessionManager & sessionManager, FabricTable * fabrics, SessionResumptionStorage * sessionResumptionStorage,
SessionManager & sessionManager, FabricTable * fabricTable, SessionResumptionStorage * sessionResumptionStorage,
Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate,
Optional<ReliableMessageProtocolConfig> mrpConfig = Optional<ReliableMessageProtocolConfig>::Missing());

Expand Down Expand Up @@ -168,7 +168,38 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
**/
void Clear();

void InvalidateIfPendingEstablishment();

private:
class CASESessionFabricDelegate final : public chip::FabricTable::Delegate
tehampson marked this conversation as resolved.
Show resolved Hide resolved
{
public:
CASESessionFabricDelegate(CASESession * caseSession)
: mCASESession(caseSession) {}

void OnFabricHasChanged(FabricTable & fabricTable, FabricIndex fabricIndex, bool fabricDeleted) override
{
(void) fabricTable;
(void) fabricIndex;
mCASESession->InvalidateIfPendingEstablishment();
tehampson marked this conversation as resolved.
Show resolved Hide resolved
}

void OnFabricRetrievedFromStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
{
(void) fabricTable;
(void) fabricIndex;
}

void OnFabricPersistedToStorage(FabricTable & fabricTable, FabricIndex fabricIndex) override
{
(void) fabricTable;
(void) fabricIndex;
}

private:
CASESession * mCASESession;
};

enum class State : uint8_t
{
kInitialized = 0,
Expand Down Expand Up @@ -223,6 +254,8 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
void OnSuccessStatusReport() override;
CHIP_ERROR OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode) override;

void AbortPendingEstablish(CHIP_ERROR err);

CHIP_ERROR GetHardcodedTime();

CHIP_ERROR SetEffectiveTime();
Expand Down Expand Up @@ -257,6 +290,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
// Sigma1 initiator random, maintained to be reused post-Sigma1, such as when generating Sigma2 S2RK key
uint8_t mInitiatorRandom[kSigmaParamRandomNumberSize];

CASESessionFabricDelegate mFabricDelegate{this};
State mState;
};

Expand Down
11 changes: 11 additions & 0 deletions src/protocols/secure_channel/PairingSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ CHIP_ERROR PairingSession::DecodeMRPParametersIfPresent(TLV::Tag expectedTag, TL
return tlvReader.ExitContainer(containerType);
}

bool PairingSession::IsSessionEstablishmentInProgress()
{
if (!mSecureSessionHolder)
{
return false;
}

Transport::SecureSession * secureSession = mSecureSessionHolder->AsSecureSession();
return secureSession->IsPairing();
}

void PairingSession::Clear()
{
// Clear acts like the destructor if PairingSession, if it is call during
Expand Down
2 changes: 2 additions & 0 deletions src/protocols/secure_channel/PairingSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ class DLL_EXPORT PairingSession : public SessionDelegate
*/
CHIP_ERROR DecodeMRPParametersIfPresent(TLV::Tag expectedTag, TLV::ContiguousBufferTLVReader & tlvReader);

bool IsSessionEstablishmentInProgress();

// TODO: remove Clear, we should create a new instance instead reset the old instance.
void Clear();

Expand Down