Skip to content

Commit 69883dc

Browse files
committed
Add ability to add pending fabric at a chosen fabric index
Currently it's only possible to allocate fabric indexes sequentially starting from 1. Sparse fabric tables could be produced by adding & removing fabrics, but not directly. This allow the application to control the assignment of fabric ids directly by providing a function that overrides the next index to use. eg If an application has 3 fabrics, it can recreate the fabric table from scratch while keeping consistent indexes.
1 parent 8c8889b commit 69883dc

File tree

3 files changed

+97
-16
lines changed

3 files changed

+97
-16
lines changed

src/credentials/FabricTable.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -2124,4 +2124,16 @@ CHIP_ERROR FabricTable::PeekFabricIndexForNextAddition(FabricIndex & outIndex)
21242124
return CHIP_NO_ERROR;
21252125
}
21262126

2127+
CHIP_ERROR FabricTable::SetFabricIndexForNextAddition(FabricIndex fabricIndex)
2128+
{
2129+
VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent), CHIP_ERROR_INCORRECT_STATE);
2130+
VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
2131+
2132+
const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex);
2133+
VerifyOrReturnError(fabricInfo == nullptr, CHIP_ERROR_FABRIC_EXISTS);
2134+
2135+
mNextAvailableFabricIndex.SetValue(fabricIndex);
2136+
return CHIP_NO_ERROR;
2137+
}
2138+
21272139
} // namespace chip

src/credentials/FabricTable.h

+7
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,13 @@ class DLL_EXPORT FabricTable
10031003
*/
10041004
CHIP_ERROR PeekFabricIndexForNextAddition(FabricIndex & outIndex);
10051005

1006+
/**
1007+
* Set the fabric index that will be used fo the next fabric added.
1008+
*
1009+
* Returns an error if the |fabricIndex| is already in use.
1010+
*/
1011+
CHIP_ERROR SetFabricIndexForNextAddition(FabricIndex fabricIndex);
1012+
10061013
private:
10071014
enum class StateFlags : uint16_t
10081015
{

src/credentials/tests/TestFabricTable.cpp

+78-16
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ class ScopedFabricTable
7979
chip::Credentials::PersistentStorageOpCertStore mOpCertStore;
8080
};
8181

82+
// These two fabric ids are supposed to be the same; only the trust root is
83+
// different.
84+
constexpr FabricId kNode01_01_FabricId = 0xFAB000000000001D;
85+
constexpr FabricId kNode02_01_FabricId = 0xFAB000000000001D;
86+
8287
/**
8388
* Load a single test fabric with with the Root01:ICA01:Node01_01 identity.
8489
*/
@@ -183,6 +188,18 @@ static CHIP_ERROR LoadTestFabric_Node02_01(FabricTable & fabricTable, bool doCom
183188
return err;
184189
}
185190

191+
const FabricInfo * FindFabric(FabricTable & fabricTable, ByteSpan rootPublicKey, FabricId fabricId)
192+
{
193+
Crypto::P256PublicKey key;
194+
EXPECT_GE(key.Length(), rootPublicKey.size());
195+
if (key.Length() < rootPublicKey.size())
196+
{
197+
return nullptr;
198+
}
199+
memcpy(key.Bytes(), rootPublicKey.data(), rootPublicKey.size());
200+
return fabricTable.FindFabric(key, fabricId);
201+
}
202+
186203
struct TestFabricTable : public ::testing::Test
187204
{
188205

@@ -2281,14 +2298,7 @@ TEST_F(TestFabricTable, TestFabricLookup)
22812298

22822299
// Attempt lookup of the Root01 fabric.
22832300
{
2284-
Crypto::P256PublicKey key;
2285-
EXPECT_GE(key.Length(), TestCerts::sTestCert_Root01_PublicKey.size());
2286-
if (key.Length() < TestCerts::sTestCert_Root01_PublicKey.size())
2287-
{
2288-
return;
2289-
}
2290-
memcpy(key.Bytes(), TestCerts::sTestCert_Root01_PublicKey.data(), TestCerts::sTestCert_Root01_PublicKey.size());
2291-
auto fabricInfo = fabricTable.FindFabric(key, 0xFAB000000000001D);
2301+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root01_PublicKey, kNode01_01_FabricId);
22922302
ASSERT_NE(fabricInfo, nullptr);
22932303

22942304
EXPECT_EQ(fabricInfo->GetFabricIndex(), 1);
@@ -2297,14 +2307,7 @@ TEST_F(TestFabricTable, TestFabricLookup)
22972307

22982308
// Attempt lookup of the Root02 fabric.
22992309
{
2300-
Crypto::P256PublicKey key;
2301-
EXPECT_GE(key.Length(), TestCerts::sTestCert_Root02_PublicKey.size());
2302-
if (key.Length() < TestCerts::sTestCert_Root02_PublicKey.size())
2303-
{
2304-
return;
2305-
}
2306-
memcpy(key.Bytes(), TestCerts::sTestCert_Root02_PublicKey.data(), TestCerts::sTestCert_Root02_PublicKey.size());
2307-
auto fabricInfo = fabricTable.FindFabric(key, 0xFAB000000000001D);
2310+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root02_PublicKey, kNode02_01_FabricId);
23082311
ASSERT_NE(fabricInfo, nullptr);
23092312

23102313
EXPECT_EQ(fabricInfo->GetFabricIndex(), 2);
@@ -2317,6 +2320,65 @@ TEST_F(TestFabricTable, TestFabricLookup)
23172320
}
23182321
}
23192322

2323+
TEST_F(TestFabricTable, ShouldFailSetFabricIndexWithInvalidIndex)
2324+
{
2325+
chip::TestPersistentStorageDelegate testStorage;
2326+
ScopedFabricTable fabricTableHolder;
2327+
EXPECT_EQ(fabricTableHolder.Init(&testStorage), CHIP_NO_ERROR);
2328+
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
2329+
2330+
EXPECT_EQ(fabricTable.SetFabricIndexForNextAddition(kUndefinedFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
2331+
}
2332+
2333+
TEST_F(TestFabricTable, ShouldFailSetFabricIndexWithPendingFabric)
2334+
{
2335+
chip::TestPersistentStorageDelegate testStorage;
2336+
ScopedFabricTable fabricTableHolder;
2337+
EXPECT_EQ(fabricTableHolder.Init(&testStorage), CHIP_NO_ERROR);
2338+
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
2339+
2340+
EXPECT_EQ(fabricTable.AddNewPendingTrustedRootCert(ByteSpan(TestCerts::sTestCert_Root01_Chip)), CHIP_NO_ERROR);
2341+
2342+
EXPECT_EQ(fabricTable.SetFabricIndexForNextAddition(1), CHIP_ERROR_INCORRECT_STATE);
2343+
}
2344+
2345+
TEST_F(TestFabricTable, ShouldFailSetFabricIndexWhenInUse)
2346+
{
2347+
chip::TestPersistentStorageDelegate testStorage;
2348+
ScopedFabricTable fabricTableHolder;
2349+
EXPECT_EQ(fabricTableHolder.Init(&testStorage), CHIP_NO_ERROR);
2350+
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
2351+
2352+
EXPECT_EQ(LoadTestFabric_Node01_01(fabricTable, /* doCommit = */ true), CHIP_NO_ERROR);
2353+
EXPECT_EQ(fabricTable.SetFabricIndexForNextAddition(1), CHIP_ERROR_FABRIC_EXISTS);
2354+
}
2355+
2356+
TEST_F(TestFabricTable, ShouldAddFabricAtRequestedIndex)
2357+
{
2358+
chip::TestPersistentStorageDelegate testStorage;
2359+
ScopedFabricTable fabricTableHolder;
2360+
EXPECT_EQ(fabricTableHolder.Init(&testStorage), CHIP_NO_ERROR);
2361+
FabricTable & fabricTable = fabricTableHolder.GetFabricTable();
2362+
2363+
EXPECT_EQ(fabricTable.SetFabricIndexForNextAddition(2), CHIP_NO_ERROR);
2364+
EXPECT_EQ(LoadTestFabric_Node02_01(fabricTable, /* doCommit = */ true), CHIP_NO_ERROR);
2365+
2366+
EXPECT_EQ(fabricTable.SetFabricIndexForNextAddition(1), CHIP_NO_ERROR);
2367+
EXPECT_EQ(LoadTestFabric_Node01_01(fabricTable, /* doCommit = */ true), CHIP_NO_ERROR);
2368+
2369+
{
2370+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root01_PublicKey, kNode01_01_FabricId);
2371+
ASSERT_NE(fabricInfo, nullptr);
2372+
EXPECT_EQ(fabricInfo->GetFabricIndex(), 1);
2373+
}
2374+
2375+
{
2376+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root02_PublicKey, kNode02_01_FabricId);
2377+
ASSERT_NE(fabricInfo, nullptr);
2378+
EXPECT_EQ(fabricInfo->GetFabricIndex(), 2);
2379+
}
2380+
}
2381+
23202382
TEST_F(TestFabricTable, TestFetchCATs)
23212383
{
23222384
// Initialize a fabric table.

0 commit comments

Comments
 (0)