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

matter: samples: Implement factory reset for persistent storage #20803

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions applications/matter_bridge/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "app_task.h"

#include <bridge/bridge_storage_manager.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
Expand All @@ -17,3 +18,8 @@ int main()
LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE;
}

bool AppFactoryResetHandler()
{
return Nrf::BridgeStorageManager::Instance().FactoryReset();
}
11 changes: 10 additions & 1 deletion samples/matter/common/src/bridge/bridge_storage_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ template <> bool BridgeStorageManager::LoadBridgedDevice(BridgedDeviceV2 &device

bool BridgeStorageManager::Init()
{
const PSErrorCode status = Nrf::GetPersistentStorage().NonSecureInit();
const PSErrorCode status = Nrf::GetPersistentStorage().NonSecureInit("br");

if (status != PSErrorCode::Success) {
return false;
Expand All @@ -198,6 +198,15 @@ bool BridgeStorageManager::Init()
return MigrateData();
}

bool BridgeStorageManager::FactoryReset()
{
#ifndef CONFIG_CHIP_FACTORY_RESET_ERASE_SETTINGS
return Nrf::PSErrorCode::Success == Nrf::GetPersistentStorage().NonSecureFactoryReset();
#else
return true;
#endif
}

#ifdef CONFIG_BRIDGE_MIGRATE_PRE_2_7_0
bool BridgeStorageManager::MigrateDataOldScheme(uint8_t bridgedDeviceIndex)
{
Expand Down
8 changes: 8 additions & 0 deletions samples/matter/common/src/bridge/bridge_storage_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ class BridgeStorageManager {
*/
bool Init();

/**
* @brief Factory reset the storage.
*
* @return true if success.
* @return false otherwise.
*/
bool FactoryReset();

/**
* @brief Store bridged devices count into settings
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ namespace Nrf
PersistentStorageSecure::UidMap PersistentStorageSecure::sUidMap{};
PersistentStorageSecure::Byte PersistentStorageSecure::sSerializedMapBuff[kMaxMapSerializationBufferSize]{};

PSErrorCode PersistentStorageSecure::_SecureInit()
PSErrorCode PersistentStorageSecure::_SecureInit(const char *prefix)
{
// Ignored in this backend
(void)prefix;

return LoadUIDMap();
}

Expand Down Expand Up @@ -85,6 +88,28 @@ PSErrorCode PersistentStorageSecure::_SecureRemove(PersistentStorageNode *node)
return PSErrorCode::Failure;
}

PSErrorCode PersistentStorageSecure::_SecureFactoryReset()
{
PSErrorCode error = PSErrorCode::Success;

// Remove all keys
for (auto it = std::begin(sUidMap.mMap); it != std::end(sUidMap.mMap) - sUidMap.FreeSlots(); ++it) {
psa_status_t status = psa_ps_remove(it->key);
if (status != PSA_SUCCESS) {
// Set error but try to remove all keys
error = PSErrorCode::Failure;
}
}

// Remove UidMap
psa_status_t status = psa_ps_remove(kKeyOffset);
if (status != PSA_SUCCESS) {
error = PSErrorCode::Failure;
}

return error;
}

psa_storage_uid_t PersistentStorageSecure::UIDFromString(char *str, bool *alreadyInTheMap)
{
for (auto &it : sUidMap.mMap) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ namespace Nrf
{
class PersistentStorageSecure {
protected:
PSErrorCode _NonSecureInit();
PSErrorCode _NonSecureInit(const char *prefix);
PSErrorCode _NonSecureStore(PersistentStorageNode *node, const void *data, size_t dataSize);
PSErrorCode _NonSecureLoad(PersistentStorageNode *node, void *data, size_t dataMaxSize, size_t &outSize);
PSErrorCode _NonSecureHasEntry(PersistentStorageNode *node);
PSErrorCode _NonSecureRemove(PersistentStorageNode *node);
PSErrorCode _NonSecureFactoryReset();

PSErrorCode _SecureInit();
PSErrorCode _SecureInit(const char *prefix);
PSErrorCode _SecureStore(PersistentStorageNode *node, const void *data, size_t dataSize);
PSErrorCode _SecureLoad(PersistentStorageNode *node, void *data, size_t dataMaxSize, size_t &outSize);
PSErrorCode _SecureHasEntry(PersistentStorageNode *node);
PSErrorCode _SecureRemove(PersistentStorageNode *node);
PSErrorCode _SecureFactoryReset();

private:
static constexpr size_t kMaxEntriesNumber = CONFIG_NCS_SAMPLE_MATTER_SECURE_STORAGE_MAX_ENTRY_NUMBER;
Expand Down Expand Up @@ -90,7 +92,7 @@ class PersistentStorageSecure {
static Byte sSerializedMapBuff[kMaxMapSerializationBufferSize];
};

inline PSErrorCode PersistentStorageSecure::_NonSecureInit()
inline PSErrorCode PersistentStorageSecure::_NonSecureInit(const char *prefix)
{
return PSErrorCode::NotSupported;
};
Expand All @@ -117,4 +119,9 @@ inline PSErrorCode PersistentStorageSecure::_NonSecureRemove(PersistentStorageNo
return PSErrorCode::NotSupported;
}

inline PSErrorCode PersistentStorageSecure::_NonSecureFactoryReset()
{
return PSErrorCode::NotSupported;
}

} /* namespace Nrf */
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ struct ReadEntry {
bool result;
};

struct DeleteSubtreeEntry {
const char *prefix;
int result;
};

/* Random magic bytes to represent an empty value.
It is needed because Zephyr settings subsystem does not distinguish an empty value from no value. */
constexpr uint8_t kEmptyValue[] = { 0x22, 0xa6, 0x54, 0xd1, 0x39 };
Expand Down Expand Up @@ -61,12 +66,36 @@ int LoadEntryCallback(const char *name, size_t entrySize, settings_read_cb readC

return 1;
}

int DeleteSubtreeCallback(const char *name, size_t entrySize, settings_read_cb readCb, void *cbArg, void *param)
{
DeleteSubtreeEntry &entry = *static_cast<DeleteSubtreeEntry *>(param);
char fullKey[SETTINGS_MAX_NAME_LEN + 1];

// name comes from Zephyr settings subsystem so it is guaranteed to fit in the buffer.
(void)snprintf(fullKey, sizeof(fullKey), "%s/%s", entry.prefix, name);
const int result = settings_delete(fullKey);

// Return the first error, but continue removing remaining keys anyway.
if (entry.result == 0) {
entry.result = result;
}

return 0;
}

} /* namespace */

namespace Nrf
{
PSErrorCode PersistentStorageSettings::_NonSecureInit()
PSErrorCode PersistentStorageSettings::_NonSecureInit(const char *prefix)
{
if (prefix == nullptr) {
return PSErrorCode::Failure;
}

mPrefix = prefix;

return settings_load() ? PSErrorCode::Failure : PSErrorCode::Success;
}

Expand Down Expand Up @@ -160,4 +189,17 @@ bool PersistentStorageSettings::LoadEntry(const char *key, void *data, size_t da

return true;
}

PSErrorCode PersistentStorageSettings::_NonSecureFactoryReset()
{
DeleteSubtreeEntry entry{ mPrefix, 0 };
int result = settings_load_subtree_direct(mPrefix, DeleteSubtreeCallback, &entry);

if (result == 0 && entry.result == 0) {
return PSErrorCode::Success;
}

return PSErrorCode::Failure;
}

} /* namespace Nrf */
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,27 @@ namespace Nrf
{
class PersistentStorageSettings {
protected:
PSErrorCode _NonSecureInit();
PSErrorCode _NonSecureInit(const char *prefix);
PSErrorCode _NonSecureStore(PersistentStorageNode *node, const void *data, size_t dataSize);
PSErrorCode _NonSecureLoad(PersistentStorageNode *node, void *data, size_t dataMaxSize, size_t &outSize);
PSErrorCode _NonSecureHasEntry(PersistentStorageNode *node);
PSErrorCode _NonSecureRemove(PersistentStorageNode *node);
PSErrorCode _NonSecureFactoryReset();

PSErrorCode _SecureInit();
PSErrorCode _SecureInit(const char *prefix);
PSErrorCode _SecureStore(PersistentStorageNode *node, const void *data, size_t dataSize);
PSErrorCode _SecureLoad(PersistentStorageNode *node, void *data, size_t dataMaxSize, size_t &outSize);
PSErrorCode _SecureHasEntry(PersistentStorageNode *node);
PSErrorCode _SecureRemove(PersistentStorageNode *node);
PSErrorCode _SecureFactoryReset();

private:
bool LoadEntry(const char *key, void *data = nullptr, size_t dataMaxSize = 0, size_t *outSize = nullptr);

const char *mPrefix = nullptr;
};

inline PSErrorCode PersistentStorageSettings::_SecureInit()
inline PSErrorCode PersistentStorageSettings::_SecureInit(const char *prefix)
{
return PSErrorCode::NotSupported;
};
Expand All @@ -55,4 +59,9 @@ inline PSErrorCode PersistentStorageSettings::_SecureRemove(PersistentStorageNod
return PSErrorCode::NotSupported;
}

inline PSErrorCode PersistentStorageSettings::_SecureFactoryReset()
{
return PSErrorCode::NotSupported;
}

} /* namespace Nrf */
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ class PersistentStorage {
/**
* @brief Perform the initialization required before using the storage.
*
* @param prefix storage key prefix
* @return true if success.
* @return false otherwise.
*/
PSErrorCode NonSecureInit();
PSErrorCode NonSecureInit(const char *prefix);

/**
* @brief Store data into the persistent storage.
Expand Down Expand Up @@ -72,12 +73,21 @@ class PersistentStorage {
*/
PSErrorCode NonSecureRemove(PersistentStorageNode *node);

/**
* @brief Perform factory reset and remove all keys.
*
* @return true if subtree has been removed successfully.
* @return false an error occurred.
*/
PSErrorCode NonSecureFactoryReset();

/* Secure storage API counterparts.*/
PSErrorCode SecureInit();
PSErrorCode SecureInit(const char *prefix);
PSErrorCode SecureStore(PersistentStorageNode *node, const void *data, size_t dataSize);
PSErrorCode SecureLoad(PersistentStorageNode *node, void *data, size_t dataMaxSize, size_t &outSize);
PSErrorCode SecureHasEntry(PersistentStorageNode *node);
PSErrorCode SecureRemove(PersistentStorageNode *node);
PSErrorCode SecureFactoryReset();

protected:
PersistentStorage() = default;
Expand Down Expand Up @@ -107,9 +117,9 @@ inline PersistentStorageImpl *PersistentStorage::Impl()
}

/* Non secure storage API. */
inline PSErrorCode PersistentStorage::NonSecureInit()
inline PSErrorCode PersistentStorage::NonSecureInit(const char *prefix)
{
return Impl()->_NonSecureInit();
return Impl()->_NonSecureInit(prefix);
};

inline PSErrorCode PersistentStorage::NonSecureStore(PersistentStorageNode *node, const void *data, size_t dataSize)
Expand All @@ -133,10 +143,15 @@ inline PSErrorCode PersistentStorage::NonSecureRemove(PersistentStorageNode *nod
return Impl()->_NonSecureRemove(node);
}

inline PSErrorCode PersistentStorage::NonSecureFactoryReset()
{
return Impl()->_NonSecureFactoryReset();
}

/* Secure storage API. */
inline PSErrorCode PersistentStorage::SecureInit()
inline PSErrorCode PersistentStorage::SecureInit(const char *prefix)
{
return Impl()->_SecureInit();
return Impl()->_SecureInit(prefix);
};

inline PSErrorCode PersistentStorage::SecureStore(PersistentStorageNode *node, const void *data, size_t dataSize)
Expand All @@ -160,4 +175,9 @@ inline PSErrorCode PersistentStorage::SecureRemove(PersistentStorageNode *node)
return Impl()->_SecureRemove(node);
}

inline PSErrorCode PersistentStorage::SecureFactoryReset()
{
return Impl()->_SecureFactoryReset();
}

} /* namespace Nrf */
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ class PersistentStorageImpl : public PersistentStorage
friend class PersistentStorage;

#ifdef CONFIG_NCS_SAMPLE_MATTER_SETTINGS_STORAGE_BACKEND

using PersistentStorageSettings::_NonSecureHasEntry;
using PersistentStorageSettings::_NonSecureInit;
using PersistentStorageSettings::_NonSecureLoad;
using PersistentStorageSettings::_NonSecureRemove;
using PersistentStorageSettings::_NonSecureFactoryReset;
using PersistentStorageSettings::_NonSecureStore;
#endif

#ifdef CONFIG_NCS_SAMPLE_MATTER_SECURE_STORAGE_BACKEND
using PersistentStorageSecure::_SecureFactoryReset;
using PersistentStorageSecure::_SecureHasEntry;
using PersistentStorageSecure::_SecureInit;
using PersistentStorageSecure::_SecureLoad;
Expand Down
7 changes: 0 additions & 7 deletions samples/matter/lock/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,6 @@ config SHELL_CMD_BUFF_SIZE

endif

config LOCK_LEAVE_FABRIC_CLEAR_CREDENTIAL
bool "Clear all credentials assigned to given fabric index"
default y
help
This feature allows to remove all credentials which were created or modified
within the fabric which is being removed from the door lock.

config STATE_LEDS
bool "Use LEDs to indicate the device state"
default y
Expand Down
13 changes: 0 additions & 13 deletions samples/matter/lock/src/access/access_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,6 @@ template <DoorLockData::CredentialsBits CRED_BIT_MASK> class AccessManager {
*/
bool GetRequirePIN() { return mRequirePINForRemoteOperation; };

#ifdef CONFIG_LOCK_LEAVE_FABRIC_CLEAR_CREDENTIAL
/**
* @brief Clear all credentials from the fabric which is currently being removed
*
* @return true on success, false otherwise
*/
bool ClearAllCredentialsFromFabric();
#endif

#ifdef CONFIG_LOCK_ENABLE_DEBUG
/* DEBUG API allowing to retrieve internally stored credentials and user data */
void PrintCredential(CredentialTypeEnum type, uint16_t index);
Expand Down Expand Up @@ -336,10 +327,6 @@ template <DoorLockData::CredentialsBits CRED_BIT_MASK> class AccessManager {
DlCredentialStatus credentialStatus, CredentialTypeEnum credentialType,
const chip::ByteSpan &secret);

#ifdef CONFIG_LOCK_LEAVE_FABRIC_CLEAR_CREDENTIAL
static bool ClearCredential(DoorLockData::Credential &credential, uint8_t credIdx);
#endif

SetCredentialCallback mSetCredentialCallback{ nullptr };
ClearCredentialCallback mClearCredentialCallback{ nullptr };
ValidateCredentialCallback mValidateCredentialCallback{ nullptr };
Expand Down
Loading
Loading