Skip to content

Commit e95b913

Browse files
authored
Clean up partial fabric data after device is reset during CommitPendingFabricData (#37819)
* Always clean up all data in FabricTable::Delete Always try to cleanup all fabric data regardless if fabric was initialized, as there may be some partial data stored if a device was reset during committing changes to storage. Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no> * Test FabricTable Delete Test if Delete invokes delegates, as this is needed to cleanup all fabric related settings after device is reset during committing changes to storage. Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no> * Fix test Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no> * Fix return value Make Delete return the same errors as before the changes. Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no> --------- Signed-off-by: Adrian Gielniewski <adrian.gielniewski@nordicsemi.no>
1 parent 4c7bbe0 commit e95b913

File tree

3 files changed

+110
-37
lines changed

3 files changed

+110
-37
lines changed

src/credentials/FabricTable.cpp

+37-36
Original file line numberDiff line numberDiff line change
@@ -1002,39 +1002,35 @@ CHIP_ERROR FabricTable::Delete(FabricIndex fabricIndex)
10021002
}
10031003
}
10041004

1005-
if (!fabricIsInitialized)
1005+
if (fabricIsInitialized)
10061006
{
1007-
// Make sure to return the error our API promises, not whatever storage
1008-
// chose to return.
1009-
return CHIP_ERROR_NOT_FOUND;
1010-
}
1011-
1012-
// Since fabricIsInitialized was true, fabric is not null.
1013-
fabricInfo->Reset();
1014-
1015-
if (!mNextAvailableFabricIndex.HasValue())
1016-
{
1017-
// We must have been in a situation where CHIP_CONFIG_MAX_FABRICS is 254
1018-
// and our fabric table was full, so there was no valid next index. We
1019-
// have a single available index now, though; use it as
1020-
// mNextAvailableFabricIndex.
1021-
mNextAvailableFabricIndex.SetValue(fabricIndex);
1022-
}
1023-
// If StoreFabricIndexInfo fails here, that's probably OK. When we try to
1024-
// read things from storage later we will realize there is nothing for this
1025-
// index.
1026-
StoreFabricIndexInfo();
1007+
// Since fabricIsInitialized was true, fabric is not null.
1008+
fabricInfo->Reset();
10271009

1028-
// If we ever start moving the FabricInfo entries around in the array on
1029-
// delete, we should update DeleteAllFabrics to handle that.
1030-
if (mFabricCount == 0)
1031-
{
1032-
ChipLogError(FabricProvisioning, "Trying to delete a fabric, but the current fabric count is already 0");
1033-
}
1034-
else
1035-
{
1036-
mFabricCount--;
1037-
ChipLogProgress(FabricProvisioning, "Fabric (0x%x) deleted.", static_cast<unsigned>(fabricIndex));
1010+
if (!mNextAvailableFabricIndex.HasValue())
1011+
{
1012+
// We must have been in a situation where CHIP_CONFIG_MAX_FABRICS is 254
1013+
// and our fabric table was full, so there was no valid next index. We
1014+
// have a single available index now, though; use it as
1015+
// mNextAvailableFabricIndex.
1016+
mNextAvailableFabricIndex.SetValue(fabricIndex);
1017+
}
1018+
// If StoreFabricIndexInfo fails here, that's probably OK. When we try to
1019+
// read things from storage later we will realize there is nothing for this
1020+
// index.
1021+
StoreFabricIndexInfo();
1022+
1023+
// If we ever start moving the FabricInfo entries around in the array on
1024+
// delete, we should update DeleteAllFabrics to handle that.
1025+
if (mFabricCount == 0)
1026+
{
1027+
ChipLogError(FabricProvisioning, "Trying to delete a fabric, but the current fabric count is already 0");
1028+
}
1029+
else
1030+
{
1031+
mFabricCount--;
1032+
ChipLogProgress(FabricProvisioning, "Fabric (0x%x) deleted.", static_cast<unsigned>(fabricIndex));
1033+
}
10381034
}
10391035

10401036
if (mDelegateListRoot != nullptr)
@@ -1050,12 +1046,17 @@ CHIP_ERROR FabricTable::Delete(FabricIndex fabricIndex)
10501046
}
10511047
}
10521048

1053-
// Only return error after trying really hard to remove everything we could
1054-
ReturnErrorOnFailure(metadataErr);
1055-
ReturnErrorOnFailure(opKeyErr);
1056-
ReturnErrorOnFailure(opCertsErr);
1049+
if (fabricIsInitialized)
1050+
{
1051+
// Only return error after trying really hard to remove everything we could
1052+
ReturnErrorOnFailure(metadataErr);
1053+
ReturnErrorOnFailure(opKeyErr);
1054+
ReturnErrorOnFailure(opCertsErr);
10571055

1058-
return CHIP_NO_ERROR;
1056+
return CHIP_NO_ERROR;
1057+
}
1058+
1059+
return CHIP_ERROR_NOT_FOUND;
10591060
}
10601061

10611062
void FabricTable::DeleteAllFabrics()

src/credentials/FabricTable.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,15 @@ class DLL_EXPORT FabricTable
412412
No
413413
};
414414

415-
// Returns CHIP_ERROR_NOT_FOUND if there is no fabric for that index.
415+
/**
416+
* @brief Delete the fabric with given `fabricIndex`.
417+
*
418+
* @param fabricIndex - Index of fabric for deletion
419+
* @retval CHIP_NO_ERROR on success
420+
* @retval CHIP_ERROR_NOT_FOUND if there is no fabric for that index
421+
* @retval CHIP_ERROR_INVALID_ARGUMENT if any of the arguments are invalid such as too large or out of bounds
422+
* @retval other CHIP_ERROR on internal errors
423+
*/
416424
CHIP_ERROR Delete(FabricIndex fabricIndex);
417425
void DeleteAllFabrics();
418426

src/credentials/tests/TestFabricTable.cpp

+64
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ class ScopedFabricTable
7272
return mFabricTable.Init(initParams);
7373
}
7474

75+
CHIP_ERROR ReinitFabricTable(chip::TestPersistentStorageDelegate * storage)
76+
{
77+
chip::FabricTable::InitParams initParams;
78+
initParams.storage = storage;
79+
initParams.operationalKeystore = &mOpKeyStore;
80+
initParams.opCertStore = &mOpCertStore;
81+
82+
return mFabricTable.Init(initParams);
83+
}
84+
7585
FabricTable & GetFabricTable() { return mFabricTable; }
7686

7787
private:
@@ -2998,4 +3008,58 @@ TEST_F(TestFabricTable, TestCommitMarker)
29983008
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
29993009
}
30003010

3011+
class TestFabricTableDelegate : public FabricTable::Delegate
3012+
{
3013+
public:
3014+
void FabricWillBeRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override { willBeRemovedCalled = true; }
3015+
3016+
void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override { onRemovedCalled = true; }
3017+
3018+
bool willBeRemovedCalled = false;
3019+
bool onRemovedCalled = false;
3020+
};
3021+
3022+
TEST_F(TestFabricTable, Delete)
3023+
{
3024+
Credentials::TestOnlyLocalCertificateAuthority fabricCertAuthority;
3025+
EXPECT_TRUE(fabricCertAuthority.Init().IsSuccess());
3026+
3027+
chip::TestPersistentStorageDelegate storage;
3028+
ScopedFabricTable fabricTableHolder;
3029+
EXPECT_EQ(fabricTableHolder.Init(&storage), CHIP_NO_ERROR);
3030+
3031+
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
3032+
FabricId fabricId = 1;
3033+
NodeId nodeId = 10;
3034+
3035+
// Simulate AddNOC
3036+
uint8_t csrBuf[chip::Crypto::kMIN_CSR_Buffer_Size];
3037+
MutableByteSpan csrSpan{ csrBuf };
3038+
EXPECT_EQ(fabricTable.AllocatePendingOperationalKey(chip::NullOptional, csrSpan), CHIP_NO_ERROR);
3039+
3040+
EXPECT_EQ(fabricCertAuthority.SetIncludeIcac(true).GenerateNocChain(fabricId, nodeId, csrSpan).GetStatus(), CHIP_NO_ERROR);
3041+
ByteSpan rcac = fabricCertAuthority.GetRcac();
3042+
ByteSpan icac = fabricCertAuthority.GetIcac();
3043+
ByteSpan noc = fabricCertAuthority.GetNoc();
3044+
3045+
fabricTable.AddNewPendingTrustedRootCert(rcac);
3046+
3047+
constexpr uint16_t kVendorId = 0xFFF1u;
3048+
FabricIndex newFabricIndex = kUndefinedFabricIndex;
3049+
EXPECT_EQ(fabricTable.AddNewPendingFabricWithOperationalKeystore(noc, icac, kVendorId, &newFabricIndex), CHIP_NO_ERROR);
3050+
3051+
// Reinitialize FabricTable to simulate device reboot
3052+
EXPECT_EQ(fabricTableHolder.ReinitFabricTable(&storage), CHIP_NO_ERROR);
3053+
3054+
TestFabricTableDelegate fabricDelegate;
3055+
fabricTable.AddFabricDelegate(&fabricDelegate);
3056+
3057+
// Check if calling Delete invokes OnFabricRemoved on delegates
3058+
fabricTable.Delete(newFabricIndex);
3059+
EXPECT_TRUE(fabricDelegate.willBeRemovedCalled);
3060+
EXPECT_TRUE(fabricDelegate.onRemovedCalled);
3061+
3062+
fabricTable.RemoveFabricDelegate(&fabricDelegate);
3063+
}
3064+
30013065
} // namespace

0 commit comments

Comments
 (0)