[nrfconnect] Added factory data accessor implementation. (#19614)

* [nrfconnect] Added factory data accessor implementation.

The nrfconnect uses test values defined in the header
files for the factory data purpose. The data belonging
to factory data should be read from dedicated location
in flash memory.

* Added FactoryDataProvider class that overrides API
to get factory data elements.
* Added FactoryDataParser module that read factory data
partition from flash and parses cbor format to get raw
data.

* Fixed some nrfconnect builds

* Addressed review comments

* Address more review comments

In particular, don't continue booting an app if mandatory
factory data fields are missing.

* Restyled by whitespace

* Restyled by clang-format

Co-authored-by: Damian Krolik <damian.krolik@nordicsemi.no>
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Arkadiusz Bałys <arkadiusz.balys@nordicsemi.no>
diff --git a/config/nrfconnect/chip-module/CMakeLists.txt b/config/nrfconnect/chip-module/CMakeLists.txt
index 13bb2e7..92d88e9 100644
--- a/config/nrfconnect/chip-module/CMakeLists.txt
+++ b/config/nrfconnect/chip-module/CMakeLists.txt
@@ -220,6 +220,13 @@
 chip_gn_arg_bool  ("chip_automation_logging"                "false")
 chip_gn_arg_bool  ("chip_malloc_sys_heap"                   CONFIG_CHIP_MALLOC_SYS_HEAP)
 
+if (CONFIG_CHIP_FACTORY_DATA)
+    chip_gn_arg_bool  ("chip_use_transitional_commissionable_data_provider"  "false")
+    chip_gn_arg_bool  ("chip_enable_factory_data"                            "true")
+elseif (CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND)
+    chip_gn_arg_bool  ("chip_use_transitional_commissionable_data_provider"  "false")
+endif()
+
 if (CONFIG_CHIP_ROTATING_DEVICE_ID)
     chip_gn_arg_bool("chip_enable_rotating_device_id"          "true")
     chip_gn_arg_bool("chip_enable_additional_data_advertising" "true")
diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig
index 54dbe2c..94f9c64 100644
--- a/config/nrfconnect/chip-module/Kconfig
+++ b/config/nrfconnect/chip-module/Kconfig
@@ -73,6 +73,22 @@
 	help
 	  Build the application with debug symbols.
 
+config CHIP_FACTORY_DATA
+	bool "Enable Factory Data support"
+	select ZCBOR
+	help
+	  Enables support for reading factory data from flash memory partition.
+	  It requires factory_data partition to exist in the partition manager 
+	  configuration file pm_static.yml.
+
+config CHIP_FACTORY_DATA_CUSTOM_BACKEND
+	bool "Enable Factory Data custom backend"
+	depends on !CHIP_FACTORY_DATA
+	help
+	  Enables user custom factory data implementation. It cannot be used
+	  with the CHIP_FACTORY_DATA that enabled default nRF Connect factory data
+	  implementation.
+
 config CHIP_FACTORY_DATA_BUILD
 	bool "Enable Factory Data build"
 	default n
diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/all-clusters-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/all-clusters-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
index 0dfbac0..43b6043 100644
--- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
+++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
@@ -186,7 +186,14 @@
     k_timer_user_data_set(&sFunctionTimer, this);
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
index e740265..04f44f4 100644
--- a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
+++ b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
@@ -19,6 +19,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 struct k_timer;
 class AppEvent;
 class LEDWidget;
@@ -63,4 +67,8 @@
     bool mIsThreadProvisioned{ false };
     bool mIsThreadEnabled{ false };
     bool mHaveBLEConnections{ false };
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
diff --git a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/all-clusters-minimal-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
index 8f7c646..ff778d9 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
@@ -137,7 +137,14 @@
     k_timer_user_data_set(&sFunctionTimer, this);
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static chip::CommonCaseDeviceServerInitParams initParams;
     (void) initParams.InitializeStaticResourcesBeforeServerInit();
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
index e740265..04f44f4 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
@@ -19,6 +19,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 struct k_timer;
 class AppEvent;
 class LEDWidget;
@@ -63,4 +67,8 @@
     bool mIsThreadProvisioned{ false };
     bool mIsThreadEnabled{ false };
     bool mHaveBLEConnections{ false };
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
diff --git a/examples/chef/nrfconnect/prj.conf b/examples/chef/nrfconnect/prj.conf
index 71679d0..ed3dcf6 100644
--- a/examples/chef/nrfconnect/prj.conf
+++ b/examples/chef/nrfconnect/prj.conf
@@ -60,3 +60,7 @@
 # Configure CHIP shell
 CONFIG_CHIP_LIB_SHELL=y
 CONFIG_OPENTHREAD_SHELL=n
+
+# Disable factory data support. 
+CONFIG_CHIP_FACTORY_DATA=n
+CONFIG_CHIP_FACTORY_DATA_BUILD=n
diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp
index 4b98212..14ac377 100644
--- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp
+++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp
@@ -158,7 +158,14 @@
 #endif
 
     // Print initial configs
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
     static chip::CommonCaseDeviceServerInitParams initParams;
     ReturnErrorOnFailure(initParams.InitializeStaticResourcesBeforeServerInit());
     ReturnErrorOnFailure(Server::GetInstance().Init(initParams));
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppTask.h b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
index 2f72dd5..f392046 100644
--- a/examples/light-switch-app/nrfconnect/main/include/AppTask.h
+++ b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
@@ -24,6 +24,10 @@
 #include <core/CHIPError.h>
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 #ifdef CONFIG_MCUMGR_SMP_BT
 #include "DFUOverSMP.h"
 #endif
@@ -88,6 +92,10 @@
 #ifdef CONFIG_MCUMGR_SMP_BT
     static void RequestSMPAdvertisingStart(void);
 #endif
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
 
 inline AppTask & GetAppTask()
diff --git a/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf b/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf
index 1525056..7e9d26f 100644
--- a/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf
+++ b/examples/lighting-app/nrfconnect/boards/nrf52840dongle_nrf52840_no_dfu.conf
@@ -37,3 +37,7 @@
 
 # Use partition manager to configure the settings partition not to overlap with Open Bootloader
 CONFIG_PM_SINGLE_IMAGE=y
+
+# Disable factory data support. 
+CONFIG_CHIP_FACTORY_DATA=n
+CONFIG_CHIP_FACTORY_DATA_BUILD=n
diff --git a/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/lighting-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/lighting-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp
index d01a327..0b7436a 100644
--- a/examples/lighting-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp
@@ -168,7 +168,14 @@
 #endif
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/lighting-app/nrfconnect/main/include/AppTask.h b/examples/lighting-app/nrfconnect/main/include/AppTask.h
index 4b0be00..3c76f13 100644
--- a/examples/lighting-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h
@@ -24,6 +24,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 #ifdef CONFIG_CHIP_PW_RPC
 #include "Rpc.h"
 #endif
@@ -98,6 +102,10 @@
     bool mFunctionTimerActive = false;
     PWMDevice mPWMDevice;
     static AppTask sAppTask;
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
 
 inline AppTask & GetAppTask(void)
diff --git a/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/lock-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/lock-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp
index 8cd120d..19e8c3c 100644
--- a/examples/lock-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lock-app/nrfconnect/main/AppTask.cpp
@@ -156,7 +156,14 @@
 #endif
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/lock-app/nrfconnect/main/include/AppTask.h b/examples/lock-app/nrfconnect/main/include/AppTask.h
index 7fb211d..8e57d8c 100644
--- a/examples/lock-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lock-app/nrfconnect/main/include/AppTask.h
@@ -25,6 +25,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 #ifdef CONFIG_MCUMGR_SMP_BT
 #include "DFUOverSMP.h"
 #endif
@@ -82,6 +86,10 @@
     Function_t mFunction      = kFunction_NoneSelected;
     bool mFunctionTimerActive = false;
     static AppTask sAppTask;
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
 
 inline AppTask & GetAppTask(void)
diff --git a/examples/pigweed-app/nrfconnect/prj.conf b/examples/pigweed-app/nrfconnect/prj.conf
index ff25bac..c8802d3 100644
--- a/examples/pigweed-app/nrfconnect/prj.conf
+++ b/examples/pigweed-app/nrfconnect/prj.conf
@@ -62,3 +62,7 @@
 CONFIG_LOG_MODE_IMMEDIATE=y
 CONFIG_LOG_BACKEND_UART=n
 CONFIG_LOG_BACKEND_RTT=n
+
+# Disable factory data support. 
+CONFIG_CHIP_FACTORY_DATA=n
+CONFIG_CHIP_FACTORY_DATA_BUILD=n
diff --git a/examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/pump-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/pump-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/pump-app/nrfconnect/main/AppTask.cpp b/examples/pump-app/nrfconnect/main/AppTask.cpp
index 45ca1d5..35de771 100644
--- a/examples/pump-app/nrfconnect/main/AppTask.cpp
+++ b/examples/pump-app/nrfconnect/main/AppTask.cpp
@@ -154,7 +154,14 @@
 #endif
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/pump-app/nrfconnect/main/include/AppTask.h b/examples/pump-app/nrfconnect/main/include/AppTask.h
index 7ca19cd..25545ee 100644
--- a/examples/pump-app/nrfconnect/main/include/AppTask.h
+++ b/examples/pump-app/nrfconnect/main/include/AppTask.h
@@ -25,6 +25,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 #ifdef CONFIG_MCUMGR_SMP_BT
 #include "DFUOverSMP.h"
 #endif
@@ -84,6 +88,10 @@
     Function_t mFunction      = kFunction_NoneSelected;
     bool mFunctionTimerActive = false;
     static AppTask sAppTask;
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
 
 inline AppTask & GetAppTask(void)
diff --git a/examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/pump-controller-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/pump-controller-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
index 621d4f9..79b0a43 100644
--- a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
+++ b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
@@ -151,7 +151,14 @@
 #endif
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
index 7ca19cd..25545ee 100644
--- a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
+++ b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
@@ -25,6 +25,10 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 #ifdef CONFIG_MCUMGR_SMP_BT
 #include "DFUOverSMP.h"
 #endif
@@ -84,6 +88,10 @@
     Function_t mFunction      = kFunction_NoneSelected;
     bool mFunctionTimerActive = false;
     static AppTask sAppTask;
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
 
 inline AppTask & GetAppTask(void)
diff --git a/examples/shell/nrfconnect/prj.conf b/examples/shell/nrfconnect/prj.conf
index 77317f6..5dc6ee8 100644
--- a/examples/shell/nrfconnect/prj.conf
+++ b/examples/shell/nrfconnect/prj.conf
@@ -49,3 +49,7 @@
 # 32786 == 0x8012 (example shell-app)
 CONFIG_CHIP_DEVICE_PRODUCT_ID=32786
 CONFIG_CHIP_NFC_COMMISSIONING=n
+
+# Disable factory data support. 
+CONFIG_CHIP_FACTORY_DATA=n
+CONFIG_CHIP_FACTORY_DATA_BUILD=n
diff --git a/examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
index 1847733..ce42b39 100644
--- a/examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
+++ b/examples/window-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml
@@ -7,32 +7,36 @@
     size: 0x200
 app:
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0x7000
-    size: 0xf5000
+    size: 0xf4000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0x7200
-    size: 0xf4e00
+    size: 0xf3e00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
     region: flash_primary
 mcuboot_secondary:
     address: 0x0
-    size: 0xf5000
+    size: 0xf4000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0xf5000
-    size: 0x70b000
+    address: 0xf4000
+    size: 0x70c000
     device: MX25R64
     region: external_flash
diff --git a/examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
index ba02c6e..3c56dc0 100644
--- a/examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
+++ b/examples/window-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -7,21 +7,25 @@
     size: 0x200
 app:
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
 mcuboot_primary:
     orig_span: &id001
         - mcuboot_pad
         - app
     span: *id001
     address: 0xC000
-    size: 0xf0000
+    size: 0xef000
     region: flash_primary
 mcuboot_primary_app:
     orig_span: &id002
         - app
     span: *id002
     address: 0xC200
-    size: 0xefe00
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
 settings_storage:
     address: 0xfc000
     size: 0x4000
@@ -33,17 +37,17 @@
     region: ram_flash
 mcuboot_secondary:
     address: 0x0
-    size: 0xf0000
+    size: 0xef000
     device: MX25R64
     region: external_flash
 mcuboot_secondary_1:
-    address: 0xf0000
+    address: 0xef000
     size: 0x40000
     device: MX25R64
     region: external_flash
 external_flash:
-    address: 0x130000
-    size: 0x6D0000
+    address: 0x12f000
+    size: 0x6D1000
     device: MX25R64
     region: external_flash
 pcd_sram:
diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp
index 44c42ef..0c80759 100644
--- a/examples/window-app/nrfconnect/main/AppTask.cpp
+++ b/examples/window-app/nrfconnect/main/AppTask.cpp
@@ -154,7 +154,14 @@
 #endif
 
     // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+    ReturnErrorOnFailure(mFactoryDataProvider.Init());
+    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+    SetCommissionableDataProvider(&mFactoryDataProvider);
+#else
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
 
     static CommonCaseDeviceServerInitParams initParams;
     static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(kTestEventTriggerEnableKey) };
diff --git a/examples/window-app/nrfconnect/main/include/AppTask.h b/examples/window-app/nrfconnect/main/include/AppTask.h
index eb0d2f9..a082c45 100644
--- a/examples/window-app/nrfconnect/main/include/AppTask.h
+++ b/examples/window-app/nrfconnect/main/include/AppTask.h
@@ -20,6 +20,10 @@
 #include "WindowCovering.h"
 #include <platform/CHIPDeviceLayer.h>
 
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/nrfconnect/FactoryDataProvider.h>
+#endif
+
 struct k_timer;
 class AppEvent;
 class LEDWidget;
@@ -75,4 +79,8 @@
     bool mOpenButtonIsPressed{ false };
     bool mCloseButtonIsPressed{ false };
     bool mMoveTypeRecentlyChanged{ false };
+
+#if CONFIG_CHIP_FACTORY_DATA
+    chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+#endif
 };
diff --git a/src/platform/nrfconnect/BUILD.gn b/src/platform/nrfconnect/BUILD.gn
index d6a6a2d..e95a274 100644
--- a/src/platform/nrfconnect/BUILD.gn
+++ b/src/platform/nrfconnect/BUILD.gn
@@ -49,8 +49,19 @@
     "SystemPlatformConfig.h",
   ]
 
+  public = [ "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h" ]
+
   public_deps = [ "${chip_root}/src/platform:platform_base" ]
 
+  if (chip_enable_factory_data) {
+    sources += [
+      "FactoryDataParser.c",
+      "FactoryDataParser.h",
+      "FactoryDataProvider.cpp",
+      "FactoryDataProvider.h",
+    ]
+  }
+
   if (chip_enable_openthread) {
     sources += [
       "../OpenThread/OpenThreadUtils.cpp",
diff --git a/src/platform/nrfconnect/FactoryDataParser.c b/src/platform/nrfconnect/FactoryDataParser.c
new file mode 100644
index 0000000..cb627fd
--- /dev/null
+++ b/src/platform/nrfconnect/FactoryDataParser.c
@@ -0,0 +1,159 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "FactoryDataParser.h"
+
+#include <logging/log.h>
+#include <zcbor_decode.h>
+
+#include <ctype.h>
+#include <string.h>
+
+#define MAX_FACTORY_DATA_NESTING_LEVEL 3
+
+LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+
+static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value)
+{
+    uint32_t u32;
+
+    if (zcbor_uint32_decode(states, &u32))
+    {
+        *value = (uint16_t) u32;
+        return true;
+    }
+
+    return false;
+}
+
+bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData * factoryData)
+{
+    memset(factoryData, 0, sizeof(*factoryData));
+    ZCBOR_STATE_D(states, MAX_FACTORY_DATA_NESTING_LEVEL, buffer, bufferSize, 1);
+
+    bool res = zcbor_map_start_decode(states);
+    struct zcbor_string currentString;
+
+    while (res)
+    {
+        res = zcbor_tstr_decode(states, &currentString);
+
+        if (!res)
+        {
+            res = true;
+            break;
+        }
+
+        if (strncmp("hw_ver", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res                       = res && uint16_decode(states, &factoryData->hw_ver);
+            factoryData->hwVerPresent = res;
+        }
+        else if (strncmp("spake2_it", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_uint32_decode(states, &factoryData->spake2_it);
+        }
+        else if (strncmp("vendor_id", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res                          = res && uint16_decode(states, &factoryData->vendor_id);
+            factoryData->vendorIdPresent = res;
+        }
+        else if (strncmp("product_id", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res                           = res && uint16_decode(states, &factoryData->product_id);
+            factoryData->productIdPresent = res;
+        }
+        else if (strncmp("discriminator", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res                               = res && uint16_decode(states, &factoryData->discriminator);
+            factoryData->discriminatorPresent = res;
+        }
+        else if (strncmp("passcode", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_uint32_decode(states, &factoryData->passcode);
+        }
+        else if (strncmp("sn", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->sn);
+        }
+        else if (strncmp("date", (const char *) currentString.value, currentString.len) == 0)
+        {
+            // Date format is YYYY-MM-DD, so format needs to be validated and string parse to integer parts.
+            struct zcbor_string date;
+            res = res && zcbor_bstr_decode(states, &date);
+            if (date.len == 10 && isdigit(date.value[0]) && isdigit(date.value[1]) && isdigit(date.value[2]) &&
+                isdigit(date.value[3]) && date.value[4] == '-' && isdigit(date.value[5]) && isdigit(date.value[6]) &&
+                date.value[7] == '-' && isdigit(date.value[8]) && isdigit(date.value[9]))
+            {
+                factoryData->date_year =
+                    1000 * (date.value[0] - '0') + 100 * (date.value[1] - '0') + 10 * (date.value[2] - '0') + date.value[3] - '0';
+                factoryData->date_month = 10 * (date.value[5] - '0') + date.value[6] - '0';
+                factoryData->date_day   = 10 * (date.value[8] - '0') + date.value[9] - '0';
+            }
+            else
+            {
+                LOG_ERR("Parsing error - wrong date format");
+            }
+        }
+        else if (strncmp("hw_ver_str", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->hw_ver_str);
+        }
+        else if (strncmp("rd_uid", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->rd_uid);
+        }
+        else if (strncmp("dac_cert", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->dac_cert);
+        }
+        else if (strncmp("dac_key", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->dac_priv_key);
+        }
+        else if (strncmp("pai_cert", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->pai_cert);
+        }
+        else if (strncmp("spake2_salt", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->spake2_salt);
+        }
+        else if (strncmp("spake2_verifier", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->spake2_verifier);
+        }
+        else if (strncmp("vendor_name", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->vendor_name);
+        }
+        else if (strncmp("product_name", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_name);
+        }
+        else if (strncmp("user", (const char *) currentString.value, currentString.len) == 0)
+        {
+            res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->user);
+        }
+        else
+        {
+            res = res && zcbor_any_skip(states, NULL);
+        }
+    }
+
+    return res && zcbor_list_map_end_force_decode(states);
+}
diff --git a/src/platform/nrfconnect/FactoryDataParser.h b/src/platform/nrfconnect/FactoryDataParser.h
new file mode 100644
index 0000000..16e2c8d
--- /dev/null
+++ b/src/platform/nrfconnect/FactoryDataParser.h
@@ -0,0 +1,76 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct FactoryDataString
+{
+    void * data;
+    size_t len;
+};
+
+struct FactoryData
+{
+    struct FactoryDataString sn;
+    uint16_t date_year;
+    uint8_t date_month;
+    uint8_t date_day;
+    uint16_t vendor_id;
+    uint16_t product_id;
+    struct FactoryDataString vendor_name;
+    struct FactoryDataString product_name;
+    uint16_t hw_ver;
+    struct FactoryDataString hw_ver_str;
+    struct FactoryDataString rd_uid;
+    struct FactoryDataString dac_cert;
+    struct FactoryDataString dac_priv_key;
+    struct FactoryDataString pai_cert;
+    uint32_t spake2_it;
+    struct FactoryDataString spake2_salt;
+    struct FactoryDataString spake2_verifier;
+    uint16_t discriminator;
+    uint32_t passcode;
+    struct FactoryDataString user;
+
+    bool vendorIdPresent;
+    bool productIdPresent;
+    bool hwVerPresent;
+    bool discriminatorPresent;
+};
+
+/**
+ * @brief Parses raw factory data into the factory data structure.
+ *
+ * @param[in] buffer Buffer containing raw factory data.
+ * @param[in] bufferSize Size of factory data.
+ * @param[out] factoryData address of object to be filled with parsed factory data.
+ *
+ * @returns true on success, false otherwise.
+ */
+bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData * factoryData);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/nrfconnect/FactoryDataProvider.cpp b/src/platform/nrfconnect/FactoryDataProvider.cpp
new file mode 100644
index 0000000..21de656
--- /dev/null
+++ b/src/platform/nrfconnect/FactoryDataProvider.cpp
@@ -0,0 +1,335 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "FactoryDataProvider.h"
+#include <crypto/CHIPCryptoPAL.h>
+
+#include <logging/log.h>
+
+namespace chip {
+namespace {
+
+CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair)
+{
+    Crypto::P256SerializedKeypair serializedKeypair;
+    ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size()));
+    memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size());
+    memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
+    return keypair.Deserialize(serializedKeypair);
+}
+} // namespace
+
+namespace DeviceLayer {
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::Init()
+{
+    uint8_t * factoryData = nullptr;
+    size_t factoryDataSize;
+
+    CHIP_ERROR error = mFlashFactoryData.GetFactoryDataPartition(factoryData, factoryDataSize);
+
+    if (error != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to read factory data partition");
+        return error;
+    }
+
+    if (!ParseFactoryData(factoryData, factoryDataSize, &mFactoryData))
+    {
+        ChipLogError(DeviceLayer, "Failed to parse factory data");
+        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetCertificationDeclaration(MutableByteSpan & outBuffer)
+{
+    //-> format_version = 1
+    //-> vendor_id = 0xFFF1
+    //-> product_id_array = [ 0x8000, 0x8001, 0x8002, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B,
+    // 0x800C, 0x800D, 0x800E, 0x800F, 0x8010, 0x8011, 0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x801A,
+    // 0x801B, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x8022, 0x8023, 0x8024, 0x8025, 0x8026, 0x8027, 0x8028, 0x8029,
+    // 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030, 0x8031, 0x8032, 0x8033, 0x8034, 0x8035, 0x8036, 0x8037, 0x8038,
+    // 0x8039, 0x803A, 0x803B, 0x803C, 0x803D, 0x803E, 0x803F, 0x8040, 0x8041, 0x8042, 0x8043, 0x8044, 0x8045, 0x8046, 0x8047,
+    // 0x8048, 0x8049, 0x804A, 0x804B, 0x804C, 0x804D, 0x804E, 0x804F, 0x8050, 0x8051, 0x8052, 0x8053, 0x8054, 0x8055, 0x8056,
+    // 0x8057, 0x8058, 0x8059, 0x805A, 0x805B, 0x805C, 0x805D, 0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063 ]
+    //-> device_type_id = 0x0016
+    //-> certificate_id = "ZIG20142ZB330003-24"
+    //-> security_level = 0
+    //-> security_information = 0
+    //-> version_number = 0x2694
+    //-> certification_type = 0
+    //-> dac_origin_vendor_id is not present
+    //-> dac_origin_product_id is not present
+    const uint8_t kCdForAllExamples[541] = {
+        0x30, 0x82, 0x02, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0x0a, 0x30,
+        0x82, 0x02, 0x06, 0x02, 0x01, 0x03, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
+        0x01, 0x30, 0x82, 0x01, 0x71, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x62,
+        0x04, 0x82, 0x01, 0x5e, 0x15, 0x24, 0x00, 0x01, 0x25, 0x01, 0xf1, 0xff, 0x36, 0x02, 0x05, 0x00, 0x80, 0x05, 0x01, 0x80,
+        0x05, 0x02, 0x80, 0x05, 0x03, 0x80, 0x05, 0x04, 0x80, 0x05, 0x05, 0x80, 0x05, 0x06, 0x80, 0x05, 0x07, 0x80, 0x05, 0x08,
+        0x80, 0x05, 0x09, 0x80, 0x05, 0x0a, 0x80, 0x05, 0x0b, 0x80, 0x05, 0x0c, 0x80, 0x05, 0x0d, 0x80, 0x05, 0x0e, 0x80, 0x05,
+        0x0f, 0x80, 0x05, 0x10, 0x80, 0x05, 0x11, 0x80, 0x05, 0x12, 0x80, 0x05, 0x13, 0x80, 0x05, 0x14, 0x80, 0x05, 0x15, 0x80,
+        0x05, 0x16, 0x80, 0x05, 0x17, 0x80, 0x05, 0x18, 0x80, 0x05, 0x19, 0x80, 0x05, 0x1a, 0x80, 0x05, 0x1b, 0x80, 0x05, 0x1c,
+        0x80, 0x05, 0x1d, 0x80, 0x05, 0x1e, 0x80, 0x05, 0x1f, 0x80, 0x05, 0x20, 0x80, 0x05, 0x21, 0x80, 0x05, 0x22, 0x80, 0x05,
+        0x23, 0x80, 0x05, 0x24, 0x80, 0x05, 0x25, 0x80, 0x05, 0x26, 0x80, 0x05, 0x27, 0x80, 0x05, 0x28, 0x80, 0x05, 0x29, 0x80,
+        0x05, 0x2a, 0x80, 0x05, 0x2b, 0x80, 0x05, 0x2c, 0x80, 0x05, 0x2d, 0x80, 0x05, 0x2e, 0x80, 0x05, 0x2f, 0x80, 0x05, 0x30,
+        0x80, 0x05, 0x31, 0x80, 0x05, 0x32, 0x80, 0x05, 0x33, 0x80, 0x05, 0x34, 0x80, 0x05, 0x35, 0x80, 0x05, 0x36, 0x80, 0x05,
+        0x37, 0x80, 0x05, 0x38, 0x80, 0x05, 0x39, 0x80, 0x05, 0x3a, 0x80, 0x05, 0x3b, 0x80, 0x05, 0x3c, 0x80, 0x05, 0x3d, 0x80,
+        0x05, 0x3e, 0x80, 0x05, 0x3f, 0x80, 0x05, 0x40, 0x80, 0x05, 0x41, 0x80, 0x05, 0x42, 0x80, 0x05, 0x43, 0x80, 0x05, 0x44,
+        0x80, 0x05, 0x45, 0x80, 0x05, 0x46, 0x80, 0x05, 0x47, 0x80, 0x05, 0x48, 0x80, 0x05, 0x49, 0x80, 0x05, 0x4a, 0x80, 0x05,
+        0x4b, 0x80, 0x05, 0x4c, 0x80, 0x05, 0x4d, 0x80, 0x05, 0x4e, 0x80, 0x05, 0x4f, 0x80, 0x05, 0x50, 0x80, 0x05, 0x51, 0x80,
+        0x05, 0x52, 0x80, 0x05, 0x53, 0x80, 0x05, 0x54, 0x80, 0x05, 0x55, 0x80, 0x05, 0x56, 0x80, 0x05, 0x57, 0x80, 0x05, 0x58,
+        0x80, 0x05, 0x59, 0x80, 0x05, 0x5a, 0x80, 0x05, 0x5b, 0x80, 0x05, 0x5c, 0x80, 0x05, 0x5d, 0x80, 0x05, 0x5e, 0x80, 0x05,
+        0x5f, 0x80, 0x05, 0x60, 0x80, 0x05, 0x61, 0x80, 0x05, 0x62, 0x80, 0x05, 0x63, 0x80, 0x18, 0x24, 0x03, 0x16, 0x2c, 0x04,
+        0x13, 0x5a, 0x49, 0x47, 0x32, 0x30, 0x31, 0x34, 0x32, 0x5a, 0x42, 0x33, 0x33, 0x30, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x34,
+        0x24, 0x05, 0x00, 0x24, 0x06, 0x00, 0x25, 0x07, 0x94, 0x26, 0x24, 0x08, 0x00, 0x18, 0x31, 0x7d, 0x30, 0x7b, 0x02, 0x01,
+        0x03, 0x80, 0x14, 0x62, 0xfa, 0x82, 0x33, 0x59, 0xac, 0xfa, 0xa9, 0x96, 0x3e, 0x1c, 0xfa, 0x14, 0x0a, 0xdd, 0xf5, 0x04,
+        0xf3, 0x71, 0x60, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0a, 0x06, 0x08,
+        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x24, 0xe5, 0xd1, 0xf4, 0x7a, 0x7d,
+        0x7b, 0x0d, 0x20, 0x6a, 0x26, 0xef, 0x69, 0x9b, 0x7c, 0x97, 0x57, 0xb7, 0x2d, 0x46, 0x90, 0x89, 0xde, 0x31, 0x92, 0xe6,
+        0x78, 0xc7, 0x45, 0xe7, 0xf6, 0x0c, 0x02, 0x21, 0x00, 0xf8, 0xaa, 0x2f, 0xa7, 0x11, 0xfc, 0xb7, 0x9b, 0x97, 0xe3, 0x97,
+        0xce, 0xda, 0x66, 0x7b, 0xae, 0x46, 0x4e, 0x2b, 0xd3, 0xff, 0xdf, 0xc3, 0xcc, 0xed, 0x7a, 0xa8, 0xca, 0x5f, 0x4c, 0x1a,
+        0x7c,
+    };
+
+    return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer);
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
+{
+    out_firmware_info_buffer.reduce_size(0);
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetDeviceAttestationCert(MutableByteSpan & outBuffer)
+{
+    ReturnErrorCodeIf(outBuffer.size() < mFactoryData.dac_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.dac_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(outBuffer.data(), mFactoryData.dac_cert.data, mFactoryData.dac_cert.len);
+
+    outBuffer.reduce_size(mFactoryData.dac_cert.len);
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer)
+{
+    ReturnErrorCodeIf(outBuffer.size() < mFactoryData.pai_cert.len, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.pai_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(outBuffer.data(), mFactoryData.pai_cert.data, mFactoryData.pai_cert.len);
+
+    outBuffer.reduce_size(mFactoryData.pai_cert.len);
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SignWithDeviceAttestationKey(const ByteSpan & digestToSign,
+                                                                               MutableByteSpan & outSignBuffer)
+{
+    Crypto::P256ECDSASignature signature;
+    Crypto::P256Keypair keypair;
+
+    VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.dac_cert.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    ReturnErrorCodeIf(!mFactoryData.dac_priv_key.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    // Extract public key from DAC cert.
+    ByteSpan dacCertSpan{ reinterpret_cast<uint8_t *>(mFactoryData.dac_cert.data), mFactoryData.dac_cert.len };
+    chip::Crypto::P256PublicKey dacPublicKey;
+
+    ReturnErrorOnFailure(chip::Crypto::ExtractPubkeyFromX509Cert(dacCertSpan, dacPublicKey));
+    ReturnErrorOnFailure(
+        LoadKeypairFromRaw(ByteSpan(reinterpret_cast<uint8_t *>(mFactoryData.dac_priv_key.data), mFactoryData.dac_priv_key.len),
+                           ByteSpan(dacPublicKey.Bytes(), dacPublicKey.Length()), keypair));
+    ReturnErrorOnFailure(keypair.ECDSA_sign_hash(digestToSign.data(), digestToSign.size(), signature));
+
+    return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+    VerifyOrReturnError(mFactoryData.discriminatorPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    setupDiscriminator = mFactoryData.discriminator;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupDiscriminator(uint16_t setupDiscriminator)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+    ReturnErrorCodeIf(mFactoryData.spake2_it == 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    iterationCount = mFactoryData.spake2_it;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+    ReturnErrorCodeIf(saltBuf.size() < mFactoryData.spake2_salt.len, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.spake2_salt.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(saltBuf.data(), mFactoryData.spake2_salt.data, mFactoryData.spake2_salt.len);
+
+    saltBuf.reduce_size(mFactoryData.spake2_salt.len);
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+    ReturnErrorCodeIf(verifierBuf.size() < mFactoryData.spake2_verifier.len, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.spake2_verifier.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(verifierBuf.data(), mFactoryData.spake2_verifier.data, mFactoryData.spake2_verifier.len);
+
+    verifierLen = mFactoryData.spake2_verifier.len;
+
+    verifierBuf.reduce_size(verifierLen);
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSetupPasscode(uint32_t & setupPasscode)
+{
+    ReturnErrorCodeIf(mFactoryData.passcode == 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    setupPasscode = mFactoryData.passcode;
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupPasscode(uint32_t setupPasscode)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorName(char * buf, size_t bufSize)
+{
+    ReturnErrorCodeIf(bufSize < mFactoryData.vendor_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.vendor_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(buf, mFactoryData.vendor_name.data, mFactoryData.vendor_name.len);
+    buf[mFactoryData.vendor_name.len] = 0;
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorId(uint16_t & vendorId)
+{
+    VerifyOrReturnError(mFactoryData.vendorIdPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    vendorId = mFactoryData.vendor_id;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductName(char * buf, size_t bufSize)
+{
+    ReturnErrorCodeIf(bufSize < mFactoryData.product_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.product_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(buf, mFactoryData.product_name.data, mFactoryData.product_name.len);
+    buf[mFactoryData.product_name.len] = 0;
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductId(uint16_t & productId)
+{
+    VerifyOrReturnError(mFactoryData.productIdPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    productId = mFactoryData.product_id;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSerialNumber(char * buf, size_t bufSize)
+{
+    ReturnErrorCodeIf(bufSize < mFactoryData.sn.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.sn.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(buf, mFactoryData.sn.data, mFactoryData.sn.len);
+    buf[mFactoryData.sn.len] = 0;
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+    VerifyOrReturnError(mFactoryData.date_year != 0, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    year  = mFactoryData.date_year;
+    month = mFactoryData.date_month;
+    day   = mFactoryData.date_day;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+    VerifyOrReturnError(mFactoryData.hwVerPresent, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+    hardwareVersion = mFactoryData.hw_ver;
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+    ReturnErrorCodeIf(bufSize < mFactoryData.hw_ver_str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.hw_ver_str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(buf, mFactoryData.hw_ver_str.data, mFactoryData.hw_ver_str.len);
+    buf[mFactoryData.hw_ver_str.len] = 0;
+
+    return CHIP_NO_ERROR;
+}
+
+template <class FlashFactoryData>
+CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+    ReturnErrorCodeIf(uniqueIdSpan.size() < mFactoryData.rd_uid.len, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorCodeIf(!mFactoryData.rd_uid.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
+
+    memcpy(uniqueIdSpan.data(), mFactoryData.rd_uid.data, mFactoryData.rd_uid.len);
+
+    return CHIP_NO_ERROR;
+}
+
+// Fully instantiate the template class in whatever compilation unit includes this file.
+template class FactoryDataProvider<InternalFlashFactoryData>;
+template class FactoryDataProvider<ExternalFlashFactoryData>;
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nrfconnect/FactoryDataProvider.h b/src/platform/nrfconnect/FactoryDataProvider.h
new file mode 100644
index 0000000..a027135
--- /dev/null
+++ b/src/platform/nrfconnect/FactoryDataProvider.h
@@ -0,0 +1,109 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <platform/CommissionableDataProvider.h>
+#include <platform/DeviceInstanceInfoProvider.h>
+
+#include <drivers/flash.h>
+#include <pm_config.h>
+
+#include "FactoryDataParser.h"
+
+namespace chip {
+namespace DeviceLayer {
+
+struct InternalFlashFactoryData
+{
+    CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
+    {
+        data     = reinterpret_cast<uint8_t *>(PM_FACTORY_DATA_ADDRESS);
+        dataSize = PM_FACTORY_DATA_SIZE;
+        return CHIP_NO_ERROR;
+    }
+};
+
+struct ExternalFlashFactoryData
+{
+    CHIP_ERROR GetFactoryDataPartition(uint8_t *& data, size_t & dataSize)
+    {
+        int ret = flash_read(mFlashDevice, PM_FACTORY_DATA_ADDRESS, mFactoryDataBuffer, PM_FACTORY_DATA_SIZE);
+
+        if (ret != 0)
+        {
+            return CHIP_ERROR_READ_FAILED;
+        }
+
+        data     = mFactoryDataBuffer;
+        dataSize = PM_FACTORY_DATA_SIZE;
+
+        return CHIP_NO_ERROR;
+    }
+
+    const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
+    uint8_t mFactoryDataBuffer[PM_FACTORY_DATA_SIZE];
+};
+
+template <class FlashFactoryData>
+class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentialsProvider,
+                            public CommissionableDataProvider,
+                            public DeviceInstanceInfoProvider
+{
+public:
+    CHIP_ERROR Init();
+
+    // ===== Members functions that implement the DeviceAttestationCredentialsProvider
+    CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
+    CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) override;
+
+    // ===== Members functions that implement the CommissionableDataProvider
+    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override;
+    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override;
+    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override;
+
+    // ===== Members functions that implement the DeviceInstanceInfoProvider
+    CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
+    CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductId(uint16_t & productId) override;
+    CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
+    CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+    CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+
+private:
+    static constexpr uint16_t kFactoryDataPartitionSize    = PM_FACTORY_DATA_SIZE;
+    static constexpr uint32_t kFactoryDataPartitionAddress = PM_FACTORY_DATA_ADDRESS;
+    static constexpr uint8_t kDACPrivateKeyLength          = 32;
+    static constexpr uint8_t kDACPublicKeyLength           = 65;
+
+    struct FactoryData mFactoryData;
+    FlashFactoryData mFlashFactoryData;
+};
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nrfconnect/args.gni b/src/platform/nrfconnect/args.gni
index 64e4dcb..9028042 100644
--- a/src/platform/nrfconnect/args.gni
+++ b/src/platform/nrfconnect/args.gni
@@ -14,4 +14,7 @@
 
 declare_args() {
   chip_malloc_sys_heap = false
+
+  # Enable factory data support
+  chip_enable_factory_data = false
 }