Skip to content

Commit 6f26239

Browse files
[SL-UP] Migrate matter certificates on Series3 to a different location (#603)
1 parent 93ec22d commit 6f26239

File tree

8 files changed

+151
-21
lines changed

8 files changed

+151
-21
lines changed

examples/platform/silabs/MatterConfig.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName)
262262
mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
263263
ReturnErrorOnFailure(chip::Platform::MemoryInit());
264264
ReturnErrorOnFailure(WifiInterface::GetInstance().InitWiFiStack());
265+
// Needs to be done post InitWifiStack for 917.
266+
// TODO move it in InitWiFiStack
267+
GetPlatform().NvmInit();
265268

266269
#if CHIP_CONFIG_ENABLE_ICD_SERVER
267270
ReturnErrorOnFailure(WifiSleepManager::GetInstance().Init(&WifiInterface::GetInstance(), &WifiInterface::GetInstance()));

src/platform/silabs/KeyValueStoreManagerImpl.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "MigrationManager.h"
2525
#include <cmsis_os2.h>
2626
#include <crypto/CHIPCryptoPAL.h>
27+
#include <lib/support/ScopedBuffer.h>
2728
#include <platform/CHIPDeviceLayer.h>
2829
#include <platform/KeyValueStoreManager.h>
2930
#include <platform/silabs/SilabsConfig.h>
@@ -51,10 +52,6 @@ KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
5152

5253
CHIP_ERROR KeyValueStoreManagerImpl::Init(void)
5354
{
54-
ReturnErrorOnFailure(SilabsConfig::Init());
55-
56-
Silabs::MigrationManager::GetMigrationInstance().applyMigrations();
57-
5855
memset(mKvsKeyMap, 0, sizeof(mKvsKeyMap));
5956
size_t outLen = 0;
6057
CHIP_ERROR error = SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap,
@@ -275,33 +272,41 @@ void KeyValueStoreManagerImpl::ErasePartition(void)
275272

276273
void KeyValueStoreManagerImpl::KvsMapMigration(void)
277274
{
278-
size_t readlen = 0;
279-
constexpr uint8_t oldMaxEntires = 120;
280-
char mKvsStoredKeyString[oldMaxEntires][PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
281-
CHIP_ERROR err =
282-
SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap, reinterpret_cast<uint8_t *>(mKvsStoredKeyString),
283-
sizeof(mKvsStoredKeyString), readlen);
275+
// this migration precedes Series 3, we don't need to run it in that case
276+
#ifndef _SILICON_LABS_32B_SERIES_3
277+
size_t readlen = 0;
278+
constexpr size_t oldMaxEntries = 120;
279+
uint32_t maxStringLen = 33; // determined by constant PersistentStorageDelegate::kKeyLengthMax + 1 before migration
280+
Platform::ScopedMemoryBuffer<char> mKvsStoredKeyString;
281+
mKvsStoredKeyString.Alloc(oldMaxEntries * maxStringLen);
282+
283+
VerifyOrReturn(mKvsStoredKeyString.Get() != nullptr);
284+
285+
CHIP_ERROR err = SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_KvsStringKeyMap,
286+
reinterpret_cast<uint8_t *>(mKvsStoredKeyString.Get()),
287+
oldMaxEntries * maxStringLen, readlen);
284288

285289
if (err == CHIP_NO_ERROR)
286290
{
287-
for (uint8_t i = 0; i < oldMaxEntires; i++)
291+
for (uint8_t i = 0; i < std::min(oldMaxEntries, KeyValueStoreManagerImpl::kMaxEntries); i++)
288292
{
289-
if (mKvsStoredKeyString[i][0] != 0)
293+
char * keyString = mKvsStoredKeyString.Get() + (i * maxStringLen);
294+
if (keyString[0] != 0)
290295
{
291296
size_t dataLen = 0;
292297
uint32_t nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(i);
293298

294299
if (SilabsConfig::ConfigValueExists(nvm3Key, dataLen))
295300
{
296301
// Read old data and prefix it with the string Key for the collision prevention mechanism.
297-
size_t keyStringLen = strlen(mKvsStoredKeyString[i]);
302+
size_t keyStringLen = strlen(keyString);
298303
uint8_t * prefixedData = static_cast<uint8_t *>(Platform::MemoryAlloc(keyStringLen + dataLen));
299304
VerifyOrDie(prefixedData != nullptr);
300-
memcpy(prefixedData, mKvsStoredKeyString[i], keyStringLen);
305+
memcpy(prefixedData, keyString, keyStringLen);
301306

302307
SilabsConfig::ReadConfigValueBin(nvm3Key, prefixedData + keyStringLen, dataLen, readlen);
303308
SilabsConfig::WriteConfigValueBin(nvm3Key, prefixedData, keyStringLen + dataLen);
304-
mKvsKeyMap[i] = KeyValueStoreMgrImpl().hashKvsKeyString(mKvsStoredKeyString[i]);
309+
mKvsKeyMap[i] = KeyValueStoreMgrImpl().hashKvsKeyString(keyString);
305310
Platform::MemoryFree(prefixedData);
306311
}
307312
}
@@ -315,6 +320,7 @@ void KeyValueStoreManagerImpl::KvsMapMigration(void)
315320
// start with a fresh kvs section.
316321
KeyValueStoreMgrImpl().ErasePartition();
317322
}
323+
#endif
318324
}
319325

320326
void KeyValueStoreManagerImpl::KvsKeyMapCleanup(void * argument)

src/platform/silabs/MigrationManager.cpp

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,19 @@
1616
*/
1717

1818
#include "MigrationManager.h"
19+
#include "sl_component_catalog.h"
20+
#include "sl_core.h"
21+
#include <headers/ProvisionManager.h>
22+
#include <headers/ProvisionStorage.h>
23+
#include <lib/support/CodeUtils.h>
24+
#include <lib/support/ScopedBuffer.h>
25+
#include <lib/support/Span.h>
1926
#include <platform/CHIPDeviceLayer.h>
2027
#include <platform/silabs/SilabsConfig.h>
2128
#include <stdio.h>
2229

30+
extern uint8_t linker_static_secure_tokens_begin; // Symbol defined by the linker script needed for MigrateS3Certificates
31+
2332
using namespace ::chip::DeviceLayer::Internal;
2433
using namespace ::chip::DeviceLayer::PersistedStorage;
2534

@@ -35,25 +44,46 @@ typedef struct
3544
func_ptr migrationFunc;
3645
} migrationData_t;
3746

38-
#define COUNT_OF(A) (sizeof(A) / sizeof((A)[0]))
3947
static migrationData_t migrationTable[] = {
4048
{ .migrationGroup = 1, .migrationFunc = MigrateKvsMap },
4149
{ .migrationGroup = 2, .migrationFunc = MigrateDacProvider },
4250
{ .migrationGroup = 3, .migrationFunc = MigrateCounterConfigs },
4351
{ .migrationGroup = 4, .migrationFunc = MigrateHardwareVersion },
52+
{ .migrationGroup = 5, .migrationFunc = MigrateS3Certificates },
4453
// add any additional migration neccesary. migrationGroup should stay equal if done in the same commit or increment by 1 for
4554
// each new entry.
4655
};
4756

4857
} // namespace
4958

50-
void MigrationManager::applyMigrations()
59+
void MigrationManager::ApplyMigrations()
5160
{
61+
#ifdef SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
62+
// Suspend all other threads so they don't interfere with the migration
63+
// This is mostly targeted to the zigbee task that overwrites our certificates
64+
uint32_t threadCount = osThreadGetCount();
65+
chip::Platform::ScopedMemoryBuffer<osThreadId_t> threadIdTable;
66+
threadIdTable.Alloc(threadCount);
67+
if (threadIdTable.Get() != nullptr)
68+
{
69+
// Forms a table of the active thread ids
70+
osThreadEnumerate(threadIdTable.Get(), threadCount);
71+
for (uint8_t tIdIndex = 0; tIdIndex < threadCount; tIdIndex++)
72+
{
73+
osThreadId_t tId = threadIdTable[tIdIndex];
74+
if (tId != osThreadGetId())
75+
{
76+
osThreadSuspend(tId);
77+
}
78+
}
79+
}
80+
#endif // SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
81+
5282
uint32_t lastMigationGroupDone = 0;
5383
SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_MigrationCounter, lastMigationGroupDone);
5484

5585
uint32_t completedMigrationGroup = lastMigationGroupDone;
56-
for (uint32_t i = 0; i < COUNT_OF(migrationTable); i++)
86+
for (uint32_t i = 0; i < MATTER_ARRAY_SIZE(migrationTable); i++)
5787
{
5888
if (lastMigationGroupDone < migrationTable[i].migrationGroup)
5989
{
@@ -62,12 +92,27 @@ void MigrationManager::applyMigrations()
6292
}
6393
}
6494
SilabsConfig::WriteConfigValue(SilabsConfig::kConfigKey_MigrationCounter, completedMigrationGroup);
95+
96+
#ifdef SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
97+
// resume all threads
98+
if (threadIdTable.Get() != nullptr)
99+
{
100+
for (uint8_t tIdIndex = 0; tIdIndex < threadCount; tIdIndex++)
101+
{
102+
osThreadId_t tId = threadIdTable[tIdIndex];
103+
if (tId != osThreadGetId())
104+
{
105+
osThreadResume(tId);
106+
}
107+
}
108+
}
109+
#endif // SL_CATALOG_ZIGBEE_ZCL_FRAMEWORK_CORE_PRESENT
65110
}
66111

67112
void MigrationManager::MigrateUint16(uint32_t old_key, uint32_t new_key)
68113
{
69114
uint16_t value = 0;
70-
if (SilabsConfig::ConfigValueExists(old_key) && (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue(old_key, value)))
115+
if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue(old_key, value))
71116
{
72117
if (CHIP_NO_ERROR == SilabsConfig::WriteConfigValue(new_key, value))
73118
{
@@ -80,7 +125,7 @@ void MigrationManager::MigrateUint16(uint32_t old_key, uint32_t new_key)
80125
void MigrationManager::MigrateUint32(uint32_t old_key, uint32_t new_key)
81126
{
82127
uint32_t value = 0;
83-
if (SilabsConfig::ConfigValueExists(old_key) && (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue(old_key, value)))
128+
if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue(old_key, value))
84129
{
85130
if (CHIP_NO_ERROR == SilabsConfig::WriteConfigValue(new_key, value))
86131
{
@@ -132,6 +177,63 @@ void MigrateHardwareVersion(void)
132177
MigrationManager::MigrateUint16(kOldKey_HardwareVersion, SilabsConfig::kConfigKey_HardwareVersion);
133178
}
134179

180+
void MigrateS3Certificates()
181+
{
182+
#ifdef _SILICON_LABS_32B_SERIES_3
183+
uint32_t tokenStartAddr = reinterpret_cast<uint32_t>(&linker_static_secure_tokens_begin);
184+
uint32_t secondPageAddr = tokenStartAddr + FLASH_PAGE_SIZE;
185+
uint32_t credsBaseAddr = 0;
186+
187+
// when credentials have been provided and stored in the first page of the static token location, we temporarely migrate them to
188+
// the second page.
189+
if (CHIP_NO_ERROR == SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_Creds_Base_Addr, credsBaseAddr) &&
190+
(credsBaseAddr >= tokenStartAddr && credsBaseAddr < secondPageAddr))
191+
{
192+
uint32_t cdSize = 0;
193+
uint32_t dacSize = 0;
194+
uint32_t paiSize = 0;
195+
Provision::Manager & provision = Provision::Manager::GetInstance();
196+
197+
// Read the size of each credential type to determine the buffer size needed
198+
VerifyOrReturn(SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_Creds_CD_Size, cdSize) == CHIP_NO_ERROR);
199+
VerifyOrReturn(SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_Creds_DAC_Size, dacSize) == CHIP_NO_ERROR);
200+
VerifyOrReturn(SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_Creds_PAI_Size, paiSize) == CHIP_NO_ERROR);
201+
202+
// Depending on existing configuration, certifications could be overlapping from the first page to the second page.
203+
// To mitigate any risk, we want to read all buffer before starting to move any of them.
204+
// allocate buffers for each certificate.
205+
// ScopedMemoryBuffer will automatically free the memory when it goes out of scope.
206+
Platform::ScopedMemoryBuffer<uint8_t> dacBuffer;
207+
Platform::ScopedMemoryBuffer<uint8_t> paiBuffer;
208+
Platform::ScopedMemoryBuffer<uint8_t> cdBuffer;
209+
dacBuffer.Alloc(dacSize);
210+
VerifyOrReturn(dacBuffer.Get() != nullptr);
211+
paiBuffer.Alloc(paiSize);
212+
VerifyOrReturn(paiBuffer.Get() != nullptr);
213+
cdBuffer.Alloc(cdSize);
214+
VerifyOrReturn(cdBuffer.Get() != nullptr);
215+
216+
MutableByteSpan dacBufferSpan(dacBuffer.Get(), dacSize);
217+
MutableByteSpan paiBufferSpan(paiBuffer.Get(), paiSize);
218+
MutableByteSpan cdBufferSpan(cdBuffer.Get(), cdSize);
219+
220+
provision.Init();
221+
// Read All certificates are the current location
222+
VerifyOrReturn(provision.GetStorage().GetDeviceAttestationCert(dacBufferSpan) == CHIP_NO_ERROR);
223+
VerifyOrReturn(provision.GetStorage().GetProductAttestationIntermediateCert(paiBufferSpan) == CHIP_NO_ERROR);
224+
VerifyOrReturn(provision.GetStorage().GetCertificationDeclaration(cdBufferSpan) == CHIP_NO_ERROR);
225+
226+
provision.GetStorage().Initialize(0, 0);
227+
provision.GetStorage().SetCredentialsBaseAddress(secondPageAddr);
228+
// Write all certs back to the second page
229+
// The first set/write, after an Initialize, erases the new page. We don't need to do it explicitly.
230+
provision.GetStorage().SetDeviceAttestationCert(dacBufferSpan);
231+
provision.GetStorage().SetProductAttestationIntermediateCert(paiBufferSpan);
232+
provision.GetStorage().SetCertificationDeclaration(cdBufferSpan);
233+
}
234+
#endif //_SILICON_LABS_32B_SERIES_3
235+
}
236+
135237
} // namespace Silabs
136238
} // namespace DeviceLayer
137239
} // namespace chip

src/platform/silabs/MigrationManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class MigrationManager
3030
* User should get the object from this getter.
3131
*/
3232
static MigrationManager & GetMigrationInstance();
33-
static void applyMigrations();
33+
static void ApplyMigrations();
3434
static void MigrateUint16(uint32_t old_key, uint32_t new_key);
3535
static void MigrateUint32(uint32_t old_key, uint32_t new_key);
3636

@@ -47,6 +47,7 @@ void MigrateKvsMap(void);
4747
void MigrateDacProvider(void);
4848
void MigrateCounterConfigs(void);
4949
void MigrateHardwareVersion(void);
50+
void MigrateS3Certificates(void);
5051

5152
} // namespace Silabs
5253
} // namespace DeviceLayer

src/platform/silabs/platformAbstraction/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ source_set("common") {
2424
"${chip_root}/src/platform/silabs/platformAbstraction/SilabsPlatform.h",
2525
"${chip_root}/src/platform/silabs/platformAbstraction/SilabsPlatformBase.h",
2626
]
27+
28+
include_dirs = [ "${chip_root}/src/platform/silabs" ]
2729
public_deps = [
2830
"${chip_root}/src/app/icd/server:icd-server-config",
2931
"${chip_root}/src/lib/core",

src/platform/silabs/platformAbstraction/GsdkSpam.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ SilabsPlatform::SilabsButtonCb SilabsPlatform::mButtonCallback = nullptr;
9696

9797
CHIP_ERROR SilabsPlatform::Init(void)
9898
{
99+
NvmInit();
99100
#ifdef _SILICON_LABS_32B_SERIES_2
100101
// Read the cause of last reset.
101102
mRebootCause = RMU_ResetCauseGet();

src/platform/silabs/platformAbstraction/SilabsPlatform.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <lib/support/CodeUtils.h>
2121
#include <platform/DiagnosticDataProvider.h>
22+
#include <platform/silabs/MigrationManager.h>
2223
#include <platform/silabs/SilabsConfig.h>
2324
#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
2425

@@ -41,6 +42,13 @@ CHIP_ERROR SilabsPlatform::VerifyIfUpdated()
4142
return CHIP_NO_ERROR;
4243
}
4344

45+
CHIP_ERROR SilabsPlatform::NvmInit()
46+
{
47+
ReturnErrorOnFailure(Internal::SilabsConfig::Init());
48+
Silabs::MigrationManager::GetMigrationInstance().ApplyMigrations();
49+
return CHIP_NO_ERROR;
50+
}
51+
4452
} // namespace Silabs
4553
} // namespace DeviceLayer
4654
} // namespace chip

src/platform/silabs/platformAbstraction/SilabsPlatform.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ class SilabsPlatform : virtual public SilabsPlatformAbstractionBase
8080
*/
8181
CHIP_ERROR VerifyIfUpdated();
8282

83+
/**
84+
* @brief Initialize the nvm driver (e.g., NVM3), and execute any needed migrations.
85+
*
86+
* @return CHIP_ERROR : CHIP_NO_ERROR when succesful, a relevant CHIP_ERROR otherwise.
87+
*/
88+
CHIP_ERROR NvmInit();
89+
8390
private:
8491
friend SilabsPlatform & GetPlatform(void);
8592

0 commit comments

Comments
 (0)