diff --git a/applications/matter_bridge/src/main.cpp b/applications/matter_bridge/src/main.cpp index 0ed8a3332a0e..c525e1e4a7c4 100644 --- a/applications/matter_bridge/src/main.cpp +++ b/applications/matter_bridge/src/main.cpp @@ -6,6 +6,7 @@ #include "app_task.h" +#include #include LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL); @@ -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(); +} diff --git a/samples/matter/common/src/bridge/bridge_storage_manager.cpp b/samples/matter/common/src/bridge/bridge_storage_manager.cpp index 1e9ffbc63afd..e2e8c8b0e82a 100644 --- a/samples/matter/common/src/bridge/bridge_storage_manager.cpp +++ b/samples/matter/common/src/bridge/bridge_storage_manager.cpp @@ -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; @@ -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) { diff --git a/samples/matter/common/src/bridge/bridge_storage_manager.h b/samples/matter/common/src/bridge/bridge_storage_manager.h index aac211519c65..51a5c4fd479c 100644 --- a/samples/matter/common/src/bridge/bridge_storage_manager.h +++ b/samples/matter/common/src/bridge/bridge_storage_manager.h @@ -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 * diff --git a/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.cpp b/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.cpp index c688a6d5ef8c..f66dc816de5c 100644 --- a/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.cpp +++ b/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.cpp @@ -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(); } @@ -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) { diff --git a/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.h b/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.h index 924a1955befc..f81aa5a7e43a 100644 --- a/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.h +++ b/samples/matter/common/src/persistent_storage/backends/persistent_storage_secure.h @@ -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; @@ -90,7 +92,7 @@ class PersistentStorageSecure { static Byte sSerializedMapBuff[kMaxMapSerializationBufferSize]; }; -inline PSErrorCode PersistentStorageSecure::_NonSecureInit() +inline PSErrorCode PersistentStorageSecure::_NonSecureInit(const char *prefix) { return PSErrorCode::NotSupported; }; @@ -117,4 +119,9 @@ inline PSErrorCode PersistentStorageSecure::_NonSecureRemove(PersistentStorageNo return PSErrorCode::NotSupported; } +inline PSErrorCode PersistentStorageSecure::_NonSecureFactoryReset() +{ + return PSErrorCode::NotSupported; +} + } /* namespace Nrf */ diff --git a/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.cpp b/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.cpp index 2de6e224e846..2a94c1afd244 100644 --- a/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.cpp +++ b/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.cpp @@ -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 }; @@ -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(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; } @@ -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 */ diff --git a/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.h b/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.h index 824783bf212d..187f43a05819 100644 --- a/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.h +++ b/samples/matter/common/src/persistent_storage/backends/persistent_storage_settings.h @@ -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; }; @@ -55,4 +59,9 @@ inline PSErrorCode PersistentStorageSettings::_SecureRemove(PersistentStorageNod return PSErrorCode::NotSupported; } +inline PSErrorCode PersistentStorageSettings::_SecureFactoryReset() +{ + return PSErrorCode::NotSupported; +} + } /* namespace Nrf */ diff --git a/samples/matter/common/src/persistent_storage/persistent_storage.h b/samples/matter/common/src/persistent_storage/persistent_storage.h index d4f65bba3f97..76c27530e896 100644 --- a/samples/matter/common/src/persistent_storage/persistent_storage.h +++ b/samples/matter/common/src/persistent_storage/persistent_storage.h @@ -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. @@ -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; @@ -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) @@ -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) @@ -160,4 +175,9 @@ inline PSErrorCode PersistentStorage::SecureRemove(PersistentStorageNode *node) return Impl()->_SecureRemove(node); } +inline PSErrorCode PersistentStorage::SecureFactoryReset() +{ + return Impl()->_SecureFactoryReset(); +} + } /* namespace Nrf */ diff --git a/samples/matter/common/src/persistent_storage/persistent_storage_impl.h b/samples/matter/common/src/persistent_storage/persistent_storage_impl.h index 259b9c625878..8ec265cf7c70 100644 --- a/samples/matter/common/src/persistent_storage/persistent_storage_impl.h +++ b/samples/matter/common/src/persistent_storage/persistent_storage_impl.h @@ -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; diff --git a/samples/matter/lock/Kconfig b/samples/matter/lock/Kconfig index 8a793d210d8c..828a8b6244f0 100644 --- a/samples/matter/lock/Kconfig +++ b/samples/matter/lock/Kconfig @@ -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 diff --git a/samples/matter/lock/src/access/access_manager.h b/samples/matter/lock/src/access/access_manager.h index 6b57902d858a..3079c5ce3497 100644 --- a/samples/matter/lock/src/access/access_manager.h +++ b/samples/matter/lock/src/access/access_manager.h @@ -264,15 +264,6 @@ template 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); @@ -336,10 +327,6 @@ template 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 }; diff --git a/samples/matter/lock/src/access/access_manager_credentials.cpp b/samples/matter/lock/src/access/access_manager_credentials.cpp index b0b369fb49ed..86c67618be37 100644 --- a/samples/matter/lock/src/access/access_manager_credentials.cpp +++ b/samples/matter/lock/src/access/access_manager_credentials.cpp @@ -145,32 +145,6 @@ CHIP_ERROR AccessManager::GetCredentialUserId(uint16_t credential return CHIP_ERROR_NOT_FOUND; } -#ifdef CONFIG_LOCK_LEAVE_FABRIC_CLEAR_CREDENTIAL -template bool AccessManager::ClearAllCredentialsFromFabric() -{ - return mCredentials.ForEach([](DoorLockData::Credential &credential, uint8_t credIdx) { - /* At this point the door-lock-server already invalidated both mCreatedBy and mLastModifiedBy - of all credentials assigned to the fabric which is currently being removed */ - if (credential.mInfo.mFields.mCreatedBy == kUndefinedFabricIndex && - credential.mInfo.mFields.mLastModifiedBy == kUndefinedFabricIndex && - credential.mSecret.mDataLength != 0) { - return Instance().ClearCredential(credential, credIdx); - } - return true; - }); -} - -template -bool AccessManager::ClearCredential(DoorLockData::Credential &credential, uint8_t credIdx) -{ - credIdx++; /* DoSetCredential expects indexes starting from 1 */ - return DoSetCredential(credential, credIdx, kUndefinedFabricIndex, kUndefinedFabricIndex, - DlCredentialStatus::kAvailable, - static_cast(credential.mInfo.mFields.mCredentialType), - chip::ByteSpan()); -} -#endif - template void AccessManager::LoadCredentialsFromPersistentStorage() { uint8_t credentialData[DoorLockData::Credential::RequiredBufferSize()] = { 0 }; @@ -186,8 +160,8 @@ template void AccessManager::Load } outSize = 0; if (!AccessStorage::Instance().Load(AccessStorage::Type::CredentialsIndexes, - credentialIndexesSerialized, - sizeof(credentialIndexesSerialized), outSize, type)) { + credentialIndexesSerialized, sizeof(credentialIndexesSerialized), + outSize, type)) { LOG_INF("No stored indexes for credential of type: %d", type); continue; } @@ -203,8 +177,7 @@ template void AccessManager::Load uint16_t credentialIndex = credIndexes.mList.mIndexes[idx]; outSize = 0; if (!AccessStorage::Instance().Load(AccessStorage::Type::Credential, credentialData, - sizeof(credentialData), outSize, type, - credentialIndex)) { + sizeof(credentialData), outSize, type, credentialIndex)) { LOG_ERR("Cannot load credentials of type %d for index: %d", static_cast(type), credentialIndex); } @@ -217,7 +190,7 @@ template void AccessManager::Load } outSize = 0; if (!AccessStorage::Instance().Load(AccessStorage::Type::RequirePIN, &mRequirePINForRemoteOperation, - sizeof(mRequirePINForRemoteOperation), outSize) || + sizeof(mRequirePINForRemoteOperation), outSize) || outSize != sizeof(mRequirePINForRemoteOperation)) { LOG_DBG("Cannot load RequirePINforRemoteOperation"); } diff --git a/samples/matter/lock/src/access/access_storage.cpp b/samples/matter/lock/src/access/access_storage.cpp index 658a20ff5537..919153481106 100644 --- a/samples/matter/lock/src/access/access_storage.cpp +++ b/samples/matter/lock/src/access/access_storage.cpp @@ -53,16 +53,27 @@ bool GetStorageFreeSpace(size_t &freeBytes) #define PSStore SecureStore #define PSRemove SecureRemove #define PSLoad SecureLoad +#define PSFactoryReset SecureFactoryReset #elif defined(CONFIG_NCS_SAMPLE_MATTER_SETTINGS_STORAGE_BACKEND) #define PSInit NonSecureInit #define PSStore NonSecureStore #define PSLoad NonSecureLoad #define PSRemove NonSecureRemove +#define PSFactoryReset NonSecureFactoryReset #endif bool AccessStorage::Init() { - return (Nrf::PSErrorCode::Success == Nrf::GetPersistentStorage().PSInit()); + return Nrf::PSErrorCode::Success == Nrf::GetPersistentStorage().PSInit(kAccessPrefix); +} + +bool AccessStorage::FactoryReset() +{ +#ifndef CONFIG_CHIP_FACTORY_RESET_ERASE_SETTINGS + return Nrf::PSErrorCode::Success == Nrf::GetPersistentStorage().PSFactoryReset(); +#else + return true; +#endif } bool AccessStorage::PrepareKeyName(Type storageType, uint16_t index, uint16_t subindex) diff --git a/samples/matter/lock/src/access/access_storage.h b/samples/matter/lock/src/access/access_storage.h index 38153a0e2f54..bfcdf3984f6e 100644 --- a/samples/matter/lock/src/access/access_storage.h +++ b/samples/matter/lock/src/access/access_storage.h @@ -63,6 +63,14 @@ class AccessStorage { */ bool Init(); + /** + * @brief Factory reset the storage. + * + * @return true if success. + * @return false otherwise. + */ + bool FactoryReset(); + /** * @brief Store the entry into the persistent storage. * diff --git a/samples/matter/lock/src/main.cpp b/samples/matter/lock/src/main.cpp index 13e532423c14..6a46c8d79556 100644 --- a/samples/matter/lock/src/main.cpp +++ b/samples/matter/lock/src/main.cpp @@ -6,6 +6,7 @@ #include "app_task.h" +#include #include LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL); @@ -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 AccessStorage::Instance().FactoryReset(); +} diff --git a/west.yml b/west.yml index bba10f587fcd..2841e889a993 100644 --- a/west.yml +++ b/west.yml @@ -157,7 +157,7 @@ manifest: - name: matter repo-path: sdk-connectedhomeip path: modules/lib/matter - revision: 4c46941ef17b7b755c96c57e4ba42306cc524e1c + revision: pull/569/head west-commands: scripts/west/west-commands.yml submodules: - name: nlio