Skip to content

Commit 15487b8

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 8a64366 commit 15487b8

File tree

4 files changed

+120
-16
lines changed

4 files changed

+120
-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/CHIPCert_test_vectors.h

+20
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ extern const ByteSpan sTestCert_Node01_01_PublicKey;
140140
extern const ByteSpan sTestCert_Node01_01_PrivateKey;
141141
extern const ByteSpan sTestCert_Node01_01_SubjectKeyId;
142142
extern const ByteSpan sTestCert_Node01_01_AuthorityKeyId;
143+
inline constexpr NodeId kTestCert_Node01_01_NodeId = 0xDEDEDEDE00010001;
144+
inline constexpr FabricId kTestCert_Node01_01_FabricId = 0xFAB000000000001D;
143145

144146
extern const ByteSpan sTestCert_Node01_01_Err01_Chip;
145147

@@ -149,62 +151,80 @@ extern const ByteSpan sTestCert_Node01_02_PublicKey;
149151
extern const ByteSpan sTestCert_Node01_02_PrivateKey;
150152
extern const ByteSpan sTestCert_Node01_02_SubjectKeyId;
151153
extern const ByteSpan sTestCert_Node01_02_AuthorityKeyId;
154+
inline constexpr NodeId kTestCert_Node01_02_NodeId = 0xDEDEDEDE00010002;
155+
inline constexpr FabricId kTestCert_Node01_02_FabricId = 0xFAB000000000001D;
152156

153157
extern const ByteSpan sTestCert_Node02_01_Chip;
154158
extern const ByteSpan sTestCert_Node02_01_DER;
155159
extern const ByteSpan sTestCert_Node02_01_PublicKey;
156160
extern const ByteSpan sTestCert_Node02_01_PrivateKey;
157161
extern const ByteSpan sTestCert_Node02_01_SubjectKeyId;
158162
extern const ByteSpan sTestCert_Node02_01_AuthorityKeyId;
163+
inline constexpr NodeId kTestCert_Node02_01_NodeId = 0xDEDEDEDE00020001;
164+
inline constexpr FabricId kTestCert_Node02_01_FabricId = 0xFAB000000000001D;
159165

160166
extern const ByteSpan sTestCert_Node02_02_Chip;
161167
extern const ByteSpan sTestCert_Node02_02_DER;
162168
extern const ByteSpan sTestCert_Node02_02_PublicKey;
163169
extern const ByteSpan sTestCert_Node02_02_PrivateKey;
164170
extern const ByteSpan sTestCert_Node02_02_SubjectKeyId;
165171
extern const ByteSpan sTestCert_Node02_02_AuthorityKeyId;
172+
inline constexpr NodeId kTestCert_Node02_02_NodeId = 0xDEDEDEDE00020002;
173+
inline constexpr FabricId kTestCert_Node02_02_FabricId = 0xFAB000000000001D;
166174

167175
extern const ByteSpan sTestCert_Node02_03_Chip;
168176
extern const ByteSpan sTestCert_Node02_03_DER;
169177
extern const ByteSpan sTestCert_Node02_03_PublicKey;
170178
extern const ByteSpan sTestCert_Node02_03_PrivateKey;
171179
extern const ByteSpan sTestCert_Node02_03_SubjectKeyId;
172180
extern const ByteSpan sTestCert_Node02_03_AuthorityKeyId;
181+
inline constexpr NodeId kTestCert_Node02_03_NodeId = 0xDEDEDEDE00020003;
182+
inline constexpr FabricId kTestCert_Node02_03_FabricId = 0xFAB000000000001D;
173183

174184
extern const ByteSpan sTestCert_Node02_04_Chip;
175185
extern const ByteSpan sTestCert_Node02_04_DER;
176186
extern const ByteSpan sTestCert_Node02_04_PublicKey;
177187
extern const ByteSpan sTestCert_Node02_04_PrivateKey;
178188
extern const ByteSpan sTestCert_Node02_04_SubjectKeyId;
179189
extern const ByteSpan sTestCert_Node02_04_AuthorityKeyId;
190+
inline constexpr NodeId kTestCert_Node02_04_NodeId = 0xDEDEDEDE00020004;
191+
inline constexpr FabricId kTestCert_Node02_04_FabricId = 0xFAB000000000001D;
180192

181193
extern const ByteSpan sTestCert_Node02_05_Chip;
182194
extern const ByteSpan sTestCert_Node02_05_DER;
183195
extern const ByteSpan sTestCert_Node02_05_PublicKey;
184196
extern const ByteSpan sTestCert_Node02_05_PrivateKey;
185197
extern const ByteSpan sTestCert_Node02_05_SubjectKeyId;
186198
extern const ByteSpan sTestCert_Node02_05_AuthorityKeyId;
199+
inline constexpr NodeId kTestCert_Node02_05_NodeId = 0xDEDEDEDE00020005;
200+
inline constexpr FabricId kTestCert_Node02_05_FabricId = 0xFAB000000000001D;
187201

188202
extern const ByteSpan sTestCert_Node02_06_Chip;
189203
extern const ByteSpan sTestCert_Node02_06_DER;
190204
extern const ByteSpan sTestCert_Node02_06_PublicKey;
191205
extern const ByteSpan sTestCert_Node02_06_PrivateKey;
192206
extern const ByteSpan sTestCert_Node02_06_SubjectKeyId;
193207
extern const ByteSpan sTestCert_Node02_06_AuthorityKeyId;
208+
inline constexpr NodeId kTestCert_Node02_06_NodeId = 0xDEDEDEDE00020006;
209+
inline constexpr FabricId kTestCert_Node02_06_FabricId = 0xFAB000000000001D;
194210

195211
extern const ByteSpan sTestCert_Node02_07_Chip;
196212
extern const ByteSpan sTestCert_Node02_07_DER;
197213
extern const ByteSpan sTestCert_Node02_07_PublicKey;
198214
extern const ByteSpan sTestCert_Node02_07_PrivateKey;
199215
extern const ByteSpan sTestCert_Node02_07_SubjectKeyId;
200216
extern const ByteSpan sTestCert_Node02_07_AuthorityKeyId;
217+
inline constexpr NodeId kTestCert_Node02_07_NodeId = 0xDEDEDEDE00020007;
218+
inline constexpr FabricId kTestCert_Node02_07_FabricId = 0xFAB000000000001D;
201219

202220
extern const ByteSpan sTestCert_Node02_08_Chip;
203221
extern const ByteSpan sTestCert_Node02_08_DER;
204222
extern const ByteSpan sTestCert_Node02_08_PublicKey;
205223
extern const ByteSpan sTestCert_Node02_08_PrivateKey;
206224
extern const ByteSpan sTestCert_Node02_08_SubjectKeyId;
207225
extern const ByteSpan sTestCert_Node02_08_AuthorityKeyId;
226+
inline constexpr NodeId kTestCert_Node02_08_NodeId = 0xDEDEDEDE00020008;
227+
inline constexpr FabricId kTestCert_Node02_08_FabricId = 0xFAB000000000001D;
208228

209229
extern const ByteSpan sTestCert_PDCID01_Chip;
210230
extern const ByteSpan sTestCert_PDCID01_ChipCompact;

src/credentials/tests/TestFabricTable.cpp

+81-16
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,18 @@ static CHIP_ERROR LoadTestFabric_Node02_01(FabricTable & fabricTable, bool doCom
183183
return err;
184184
}
185185

186+
const FabricInfo * FindFabric(FabricTable & fabricTable, ByteSpan rootPublicKey, FabricId fabricId)
187+
{
188+
Crypto::P256PublicKey key;
189+
EXPECT_GE(key.Length(), rootPublicKey.size());
190+
if (key.Length() < rootPublicKey.size())
191+
{
192+
return nullptr;
193+
}
194+
memcpy(key.Bytes(), rootPublicKey.data(), rootPublicKey.size());
195+
return fabricTable.FindFabric(key, fabricId);
196+
}
197+
186198
struct TestFabricTable : public ::testing::Test
187199
{
188200

@@ -2279,16 +2291,13 @@ TEST_F(TestFabricTable, TestFabricLookup)
22792291
EXPECT_EQ(LoadTestFabric_Node01_01(fabricTable, /* doCommit = */ true), CHIP_NO_ERROR);
22802292
EXPECT_EQ(LoadTestFabric_Node02_01(fabricTable, /* doCommit = */ true, FabricTable::AdvertiseIdentity::No), CHIP_NO_ERROR);
22812293

2294+
// These two NOCs have the same fabric id on purpose; only the trust root is
2295+
// different.
2296+
constexpr FabricId kNode01_01_and_02_01_FabricId = 0xFAB000000000001D;
2297+
22822298
// Attempt lookup of the Root01 fabric.
22832299
{
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);
2300+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root01_PublicKey, kNode01_01_and_02_01_FabricId);
22922301
ASSERT_NE(fabricInfo, nullptr);
22932302

22942303
EXPECT_EQ(fabricInfo->GetFabricIndex(), 1);
@@ -2297,14 +2306,7 @@ TEST_F(TestFabricTable, TestFabricLookup)
22972306

22982307
// Attempt lookup of the Root02 fabric.
22992308
{
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);
2309+
auto fabricInfo = FindFabric(fabricTable, TestCerts::sTestCert_Root02_PublicKey, kNode01_01_and_02_01_FabricId);
23082310
ASSERT_NE(fabricInfo, nullptr);
23092311

23102312
EXPECT_EQ(fabricInfo->GetFabricIndex(), 2);
@@ -2317,6 +2319,69 @@ TEST_F(TestFabricTable, TestFabricLookup)
23172319
}
23182320
}
23192321

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

0 commit comments

Comments
 (0)