[ESP32] Device Info Provider Implementation (#21752)

* [ESP32] Device Info Provider Implementation

Changes in the factory partition generator script to include supported
calendar types, locales, and fixed labels

* Fix the order of setting deviceinfoprovider

* Introduced device info provider in esp32 apps

* Add example provider's path in CMakeLists.txt
diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt
index 4b4189d..63dff3e 100644
--- a/config/esp32/components/chip/CMakeLists.txt
+++ b/config/esp32/components/chip/CMakeLists.txt
@@ -166,6 +166,10 @@
     chip_gn_arg_append("chip_use_factory_data_provider"                     "true")
 endif()
 
+if (CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER)
+    chip_gn_arg_append("chip_use_device_info_provider"                     "true")
+endif()
+
 set(args_gn_input "${CMAKE_CURRENT_BINARY_DIR}/args.gn.in")
 file(GENERATE OUTPUT "${args_gn_input}" CONTENT "${chip_gn_args}")
 
diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig
index 587b694..867a462 100644
--- a/config/esp32/components/chip/Kconfig
+++ b/config/esp32/components/chip/Kconfig
@@ -637,6 +637,15 @@
                 Hardware Version, Hardware Version String, and Rotating Device Id UniqueId will be read from factory
                 partition.
 
+        config ENABLE_ESP32_DEVICE_INFO_PROVIDER
+            depends on ENABLE_ESP32_FACTORY_DATA_PROVIDER
+            bool "Use ESP32 Device Info Provider"
+            default n
+            help
+                Use ESP32 Device Info Provider to get device instance info from factory partition.
+                Details like Supported calendar types, supported locales, and fixed labels will be read from factory
+                partition.
+
     endmenu
 
 
diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt
index 4069745..2948a99 100644
--- a/examples/all-clusters-app/esp32/main/CMakeLists.txt
+++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt
@@ -21,7 +21,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/all-clusters-app"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
-                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"                      
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
 )
 set(SRC_DIRS_LIST
@@ -29,7 +29,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/all-clusters-app/zap-generated"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated"
-                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"                      
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp
index 4bb5415..1447638 100644
--- a/examples/all-clusters-app/esp32/main/main.cpp
+++ b/examples/all-clusters-app/esp32/main/main.cpp
@@ -34,7 +34,6 @@
 #include "nvs_flash.h"
 #include "platform/PlatformManager.h"
 #include "shell_extension/launch.h"
-#include <DeviceInfoProviderImpl.h>
 #include <app/server/OnboardingCodesUtil.h>
 #include <app/util/af.h>
 #include <binding-handler.h>
@@ -59,6 +58,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::Shell;
 using namespace ::chip::DeviceManager;
@@ -94,7 +99,11 @@
 DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
-DeviceLayer::DeviceInfoProviderImpl sExampleDeviceInfoProvider;
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 
 } // namespace
 
@@ -139,7 +148,7 @@
     ThreadStackMgr().InitThreadStack();
 #endif
 
-    DeviceLayer::SetDeviceInfoProvider(&sExampleDeviceInfoProvider);
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
 
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
     CHIP_ERROR error              = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
index 19108d2..ec9c40c 100644
--- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
+++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
@@ -21,6 +21,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/all-clusters-minimal-app"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
 )
 set(SRC_DIRS_LIST
@@ -32,6 +33,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting"
diff --git a/examples/all-clusters-minimal-app/esp32/main/main.cpp b/examples/all-clusters-minimal-app/esp32/main/main.cpp
index 118a986..a5de104 100644
--- a/examples/all-clusters-minimal-app/esp32/main/main.cpp
+++ b/examples/all-clusters-minimal-app/esp32/main/main.cpp
@@ -59,6 +59,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::Shell;
 using namespace ::chip::Credentials;
@@ -91,9 +97,15 @@
 constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
 
 #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
-chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
+DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 } // namespace
 
 static void InitServer(intptr_t context)
@@ -137,6 +149,8 @@
     ThreadStackMgr().InitThreadStack();
 #endif
 
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
     CHIP_ERROR error              = deviceMgr.Init(&EchoCallbacks);
     DeviceCallbacksDelegate::Instance().SetAppDelegate(&sAppDeviceCallbacksDelegate);
diff --git a/examples/bridge-app/esp32/main/CMakeLists.txt b/examples/bridge-app/esp32/main/CMakeLists.txt
index 4857554..5254ad2 100644
--- a/examples/bridge-app/esp32/main/CMakeLists.txt
+++ b/examples/bridge-app/esp32/main/CMakeLists.txt
@@ -17,6 +17,7 @@
 idf_component_register(PRIV_INCLUDE_DIRS
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/bridge-app"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       SRC_DIRS
                       "${CMAKE_CURRENT_LIST_DIR}"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/bridge-app/zap-generated"
@@ -50,6 +51,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       PRIV_REQUIRES chip QRCode bt)
 
 set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 14)
diff --git a/examples/bridge-app/esp32/main/main.cpp b/examples/bridge-app/esp32/main/main.cpp
index 5f3a3de..447df22 100644
--- a/examples/bridge-app/esp32/main/main.cpp
+++ b/examples/bridge-app/esp32/main/main.cpp
@@ -42,10 +42,22 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 namespace {
 #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
+
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+chip::DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 const char * TAG = "bridge-app";
@@ -410,6 +422,8 @@
     gLight3.SetChangeCallback(&HandleDeviceStatusChanged);
     gLight4.SetChangeCallback(&HandleDeviceStatusChanged);
 
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
 
     chip_err = deviceMgr.Init(&AppCallback);
diff --git a/examples/light-switch-app/esp32/main/CMakeLists.txt b/examples/light-switch-app/esp32/main/CMakeLists.txt
index 3abe09f..6a6c991 100644
--- a/examples/light-switch-app/esp32/main/CMakeLists.txt
+++ b/examples/light-switch-app/esp32/main/CMakeLists.txt
@@ -19,14 +19,14 @@
 idf_component_register(PRIV_INCLUDE_DIRS
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/light-switch-app"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
-                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"                      
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
                       SRC_DIRS
                       "${CMAKE_CURRENT_LIST_DIR}"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/light-switch-app/zap-generated"
-                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"                      
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
diff --git a/examples/light-switch-app/esp32/main/main.cpp b/examples/light-switch-app/esp32/main/main.cpp
index eec8be2..af37ae2 100644
--- a/examples/light-switch-app/esp32/main/main.cpp
+++ b/examples/light-switch-app/esp32/main/main.cpp
@@ -30,7 +30,6 @@
 #include "nvs_flash.h"
 #include "shell_extension/launch.h"
 
-#include <DeviceInfoProviderImpl.h>
 #include <app/server/OnboardingCodesUtil.h>
 #include <credentials/DeviceAttestationCredsProvider.h>
 #include <credentials/examples/DeviceAttestationCredsExample.h>
@@ -39,6 +38,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceManager;
@@ -48,7 +53,11 @@
 DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
-DeviceLayer::DeviceInfoProviderImpl sExampleDeviceInfoProvider;
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 static const char * TAG = "light-switch-app";
@@ -83,7 +92,7 @@
     chip::LaunchShell();
 #endif // CONFIG_ENABLE_CHIP_SHELL
 
-    DeviceLayer::SetDeviceInfoProvider(&sExampleDeviceInfoProvider);
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
 
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
     CHIP_ERROR error              = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/lighting-app/esp32/main/main.cpp b/examples/lighting-app/esp32/main/main.cpp
index 167acab..a551a6e 100644
--- a/examples/lighting-app/esp32/main/main.cpp
+++ b/examples/lighting-app/esp32/main/main.cpp
@@ -28,7 +28,6 @@
 #include "freertos/task.h"
 #include "nvs_flash.h"
 #include "shell_extension/launch.h"
-#include <DeviceInfoProviderImpl.h>
 #include <app/server/Dnssd.h>
 #include <app/server/OnboardingCodesUtil.h>
 #include <credentials/DeviceAttestationCredsProvider.h>
@@ -38,6 +37,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceManager;
@@ -52,7 +57,11 @@
 DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
-DeviceLayer::DeviceInfoProviderImpl sExampleDeviceInfoProvider;
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 static void InitServer(intptr_t context)
@@ -81,7 +90,7 @@
     chip::LaunchShell();
 #endif
 
-    DeviceLayer::SetDeviceInfoProvider(&sExampleDeviceInfoProvider);
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
 
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
     CHIP_ERROR error              = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/lock-app/esp32/main/main.cpp b/examples/lock-app/esp32/main/main.cpp
index 6ff5f7d..df47caa 100644
--- a/examples/lock-app/esp32/main/main.cpp
+++ b/examples/lock-app/esp32/main/main.cpp
@@ -27,7 +27,6 @@
 #include "freertos/task.h"
 #include "nvs_flash.h"
 #include "shell_extension/launch.h"
-#include <DeviceInfoProviderImpl.h>
 #include <common/CHIPDeviceManager.h>
 #include <common/Esp32AppServer.h>
 #include <credentials/DeviceAttestationCredsProvider.h>
@@ -49,6 +48,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::DeviceManager;
 using namespace ::chip::Credentials;
@@ -58,7 +63,11 @@
 DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
-DeviceLayer::DeviceInfoProviderImpl sExampleDeviceInfoProvider;
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 static const char * TAG = "lock-app";
@@ -99,7 +108,7 @@
     chip::LaunchShell();
 #endif
 
-    DeviceLayer::SetDeviceInfoProvider(&sExampleDeviceInfoProvider);
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
 
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
     CHIP_ERROR error              = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/ota-provider-app/esp32/main/CMakeLists.txt b/examples/ota-provider-app/esp32/main/CMakeLists.txt
index 15ec1ed..3142183 100644
--- a/examples/ota-provider-app/esp32/main/CMakeLists.txt
+++ b/examples/ota-provider-app/esp32/main/CMakeLists.txt
@@ -20,6 +20,7 @@
                       "${CMAKE_CURRENT_LIST_DIR}/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-provider-app/"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       SRC_DIRS
                       "${CMAKE_CURRENT_LIST_DIR}"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-provider-app/zap-generated"
@@ -53,6 +54,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       EXCLUDE_SRCS
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp"
                       PRIV_REQUIRES chip QRCode bt console spiffs)
diff --git a/examples/ota-provider-app/esp32/main/main.cpp b/examples/ota-provider-app/esp32/main/main.cpp
index f20425a..27f46ed 100644
--- a/examples/ota-provider-app/esp32/main/main.cpp
+++ b/examples/ota-provider-app/esp32/main/main.cpp
@@ -38,6 +38,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using chip::Callback::Callback;
 using namespace chip;
 using namespace chip::Shell;
@@ -138,9 +144,14 @@
 }
 
 #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
-chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
+DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 CHIP_ERROR OnBlockQuery(void * context, chip::System::PacketBufferHandle & blockBuf, size_t & size, bool & isEof, uint32_t offset)
@@ -231,6 +242,8 @@
         return;
     }
 
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
 
     CHIP_ERROR error = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/ota-requestor-app/esp32/main/CMakeLists.txt b/examples/ota-requestor-app/esp32/main/CMakeLists.txt
index 7a7ac14..53f8fd6 100644
--- a/examples/ota-requestor-app/esp32/main/CMakeLists.txt
+++ b/examples/ota-requestor-app/esp32/main/CMakeLists.txt
@@ -21,6 +21,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/ota-requestor-app/"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
 )
 
 set(SRC_DIRS_LIST
@@ -59,6 +60,7 @@
 		      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
 )
 
 set(PRIV_REQUIRES_LIST chip QRCode bt console app_update)
diff --git a/examples/ota-requestor-app/esp32/main/main.cpp b/examples/ota-requestor-app/esp32/main/main.cpp
index e9a7f0b..021fd5b 100644
--- a/examples/ota-requestor-app/esp32/main/main.cpp
+++ b/examples/ota-requestor-app/esp32/main/main.cpp
@@ -45,6 +45,12 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 using namespace ::chip;
 using namespace ::chip::System;
 using namespace ::chip::DeviceManager;
@@ -66,9 +72,14 @@
 }
 
 #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
-chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
+DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 extern "C" void app_main()
@@ -103,6 +114,8 @@
     OTARequestorCommands::GetInstance().Register();
 #endif // CONFIG_ENABLE_CHIP_SHELL
 
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
 
     CHIP_ERROR error = deviceMgr.Init(&EchoCallbacks);
diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt
index f8a313a..56e5d0a 100644
--- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt
+++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt
@@ -20,6 +20,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/temperature-measurement-app/"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
 )
 set(SRC_DIRS_LIST
                       "${CMAKE_CURRENT_LIST_DIR}"
@@ -51,6 +52,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/route_hook"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
 )
 
 set(PRIV_REQUIRES_LIST chip QRCode bt)
diff --git a/examples/temperature-measurement-app/esp32/main/main.cpp b/examples/temperature-measurement-app/esp32/main/main.cpp
index 983ff89..f42e318 100644
--- a/examples/temperature-measurement-app/esp32/main/main.cpp
+++ b/examples/temperature-measurement-app/esp32/main/main.cpp
@@ -46,10 +46,22 @@
 #include <platform/ESP32/ESP32FactoryDataProvider.h>
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#else
+#include <DeviceInfoProviderImpl.h>
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+
 namespace {
 #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
 chip::DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;
 #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
+
+#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
+chip::DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;
+#else
+chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
 } // namespace
 
 using namespace ::chip;
@@ -93,6 +105,8 @@
         return;
     }
 
+    DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
     CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
 
     CHIP_ERROR error = deviceMgr.Init(&EchoCallbacks);
diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py
index fbf73f4..d5f6ed3 100755
--- a/scripts/tools/generate_esp32_chip_factory_bin.py
+++ b/scripts/tools/generate_esp32_chip_factory_bin.py
@@ -24,6 +24,9 @@
 import subprocess
 import cryptography.x509
 from types import SimpleNamespace
+import enum
+from bitarray import bitarray
+from bitarray.util import ba2int
 
 if os.getenv('IDF_PATH'):
     sys.path.insert(0, os.path.join(os.getenv('IDF_PATH'),
@@ -141,10 +144,86 @@
         'type': 'data',
         'encoding': 'hex2bin',
         'value': None,
-    }
+    },
+    # DeviceInfoProvider
+    'cal-types': {
+        'type': 'data',
+        'encoding': 'u32',
+        'value': None,
+    },
+    'locale-sz': {
+        'type': 'data',
+        'encoding': 'u32',
+        'value': None,
+    },
+
+    # Other device info provider keys are dynamically generated
+    # in the respective functions.
 }
 
 
+class CalendarTypes(enum.Enum):
+    Buddhist = 0
+    Chinese = 1
+    Coptic = 2
+    Ethiopian = 3
+    Gregorian = 4
+    Hebrew = 5
+    Indian = 6
+    Islamic = 7
+    Japanese = 8
+    Korean = 9
+    Persian = 10
+    Taiwanese = 11
+
+
+# Supported Calendar types is stored as a bit array in one uint32_t.
+def calendar_types_to_uint32(calendar_types):
+    result = bitarray(32, endian='little')
+    result.setall(0)
+    for calendar_type in calendar_types:
+        try:
+            result[CalendarTypes[calendar_type].value] = 1
+        except KeyError:
+            logging.error('Unknown calendar type: %s', calendar_type)
+            logging.error('Supported calendar types: %s', ', '.join(CalendarTypes.__members__))
+            sys.exit(1)
+    return ba2int(result)
+
+
+def ishex(s):
+    try:
+        n = int(s, 16)
+        return True
+    except ValueError:
+        return False
+
+# get_fixed_label_dict() converts the list of strings to per endpoint dictionaries.
+# example input  : ['0/orientation/up', '1/orientation/down', '2/orientation/down']
+# example outout : {'0': [{'orientation': 'up'}], '1': [{'orientation': 'down'}], '2': [{'orientation': 'down'}]}
+
+
+def get_fixed_label_dict(fixed_labels):
+    fl_dict = {}
+    for fl in fixed_labels:
+        _l = fl.split('/')
+
+        if len(_l) != 3:
+            logging.error('Invalid fixed label: %s', fl)
+            sys.exit(1)
+
+        if not (ishex(_l[0]) and (len(_l[1]) > 0 and len(_l[1]) < 16) and (len(_l[2]) > 0 and len(_l[2]) < 16)):
+            logging.error('Invalid fixed label: %s', fl)
+            sys.exit(1)
+
+        if _l[0] not in fl_dict.keys():
+            fl_dict[_l[0]] = list()
+
+        fl_dict[_l[0]].append({_l[1]: _l[2]})
+
+    return fl_dict
+
+
 def check_tools_exists():
     TOOLS['spake2p'] = shutil.which('spake2p')
     if TOOLS['spake2p'] is None:
@@ -233,6 +312,52 @@
     if (args.hw_ver_str is not None):
         FACTORY_DATA['hw-ver-str']['value'] = args.hw_ver_str
 
+    if (args.calendar_types is not None):
+        FACTORY_DATA['cal-types']['value'] = calendar_types_to_uint32(args.calendar_types)
+
+    # Supported locale is stored as multiple entries, key format: "locale/<index>, example key: "locale/0"
+    if (args.locales is not None):
+        FACTORY_DATA['locale-sz']['value'] = len(args.locales)
+
+        for i in range(len(args.locales)):
+            _locale = {
+                'type': 'data',
+                'encoding': 'string',
+                'value': args.locales[i]
+            }
+            FACTORY_DATA.update({'locale/{:x}'.format(i): _locale})
+
+    # Each endpoint can contains the fixed lables
+    #  - fl-sz/<index>     : number of fixed labels for the endpoint
+    #  - fl-k/<ep>/<index> : fixed label key for the endpoint and index
+    #  - fl-v/<ep>/<index> : fixed label value for the endpoint and index
+    if (args.fixed_labels is not None):
+        dict = get_fixed_label_dict(args.fixed_labels)
+        for key in dict.keys():
+            _sz = {
+                'type': 'data',
+                'encoding': 'u32',
+                'value': len(dict[key])
+            }
+            FACTORY_DATA.update({'fl-sz/{:x}'.format(int(key)): _sz})
+
+            for i in range(len(dict[key])):
+                entry = dict[key][i]
+
+                _label_key = {
+                    'type': 'data',
+                    'encoding': 'string',
+                    'value': list(entry.keys())[0]
+                }
+                _label_value = {
+                    'type': 'data',
+                    'encoding': 'string',
+                    'value': list(entry.values())[0]
+                }
+
+                FACTORY_DATA.update({'fl-k/{:x}/{:x}'.format(int(key), i): _label_key})
+                FACTORY_DATA.update({'fl-v/{:x}/{:x}'.format(int(key), i): _label_value})
+
 
 def gen_raw_ec_keypair_from_der(key_file, pubkey_raw_file, privkey_raw_file):
     with open(key_file, 'rb') as f:
@@ -243,7 +368,8 @@
 
     # WARNING: Below line assumes that the DAC private key is not protected by a password,
     #          please be careful and use the password-protected key if reusing this code
-    key_der = cryptography.hazmat.primitives.serialization.load_der_private_key(key_data, None)
+    key_der = cryptography.hazmat.primitives.serialization.load_der_private_key(
+        key_data, None, cryptography.hazmat.backends.default_backend())
 
     private_number_val = key_der.private_numbers().private_value
     with open(privkey_raw_file, 'wb') as f:
@@ -337,6 +463,14 @@
     parser.add_argument('--unique-id', type=str, required=False,
                         help='128-bit unique identifier, provide 32-byte hex string, e.g. "1234567890abcdef1234567890abcdef"')
 
+    # These will be used by DeviceInfoProvider
+    parser.add_argument('--calendar-types', type=str, nargs='+', required=False,
+                        help='List of supported calendar types.\nSupported Calendar Types: Buddhist, Chinese, Coptic, Ethiopian, Gregorian, Hebrew, Indian, Islamic, Japanese, Korean, Persian, Taiwanese')
+    parser.add_argument('--locales', type=str, nargs='+', required=False,
+                        help='List of supported locales, Language Tag as defined by BCP47, eg. en-US en-GB')
+    parser.add_argument('--fixed-labels', type=str, nargs='+', required=False,
+                        help='List of fixed labels, eg: "0/orientation/up" "1/orientation/down" "2/orientation/down"')
+
     parser.add_argument('-s', '--size', type=any_base_int, required=False, default=0x6000,
                         help='The size of the partition.bin, default: 0x6000')
     parser.add_argument('-e', '--encrypt', action='store_true', required=False,
diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn
index 9f38280..7af8b30 100644
--- a/src/platform/ESP32/BUILD.gn
+++ b/src/platform/ESP32/BUILD.gn
@@ -22,6 +22,7 @@
   # By default use default/example implementation of CommissionableDataProvider,
   # DeviceAttestationCredentialsProvider and DeviceInstanceInforProvider
   chip_use_factory_data_provider = false
+  chip_use_device_info_provider = false
 }
 
 static_library("ESP32") {
@@ -107,4 +108,11 @@
       "ESP32FactoryDataProvider.h",
     ]
   }
+
+  if (chip_use_device_info_provider) {
+    sources += [
+      "ESP32DeviceInfoProvider.cpp",
+      "ESP32DeviceInfoProvider.h",
+    ]
+  }
 }
diff --git a/src/platform/ESP32/ESP32Config.cpp b/src/platform/ESP32/ESP32Config.cpp
index b6f07c6..0feaa56 100644
--- a/src/platform/ESP32/ESP32Config.cpp
+++ b/src/platform/ESP32/ESP32Config.cpp
@@ -73,6 +73,8 @@
 const ESP32Config::Key ESP32Config::kConfigKey_ProductId             = { kConfigNamespace_ChipFactory, "product-id" };
 const ESP32Config::Key ESP32Config::kConfigKey_ProductName           = { kConfigNamespace_ChipFactory, "product-name" };
 const ESP32Config::Key ESP32Config::kConfigKey_UniqueId              = { kConfigNamespace_ChipFactory, "unique-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_SupportedCalTypes     = { kConfigNamespace_ChipFactory, "cal-types" };
+const ESP32Config::Key ESP32Config::kConfigKey_SupportedLocaleSize   = { kConfigNamespace_ChipFactory, "locale-sz" };
 
 // Keys stored in the chip-config namespace
 const ESP32Config::Key ESP32Config::kConfigKey_ServiceConfig      = { kConfigNamespace_ChipConfig, "service-config" };
diff --git a/src/platform/ESP32/ESP32Config.h b/src/platform/ESP32/ESP32Config.h
index a0ec2a1..8613836 100644
--- a/src/platform/ESP32/ESP32Config.h
+++ b/src/platform/ESP32/ESP32Config.h
@@ -41,6 +41,7 @@
 {
 public:
     struct Key;
+    class KeyAllocator;
 
     // Maximum length of an NVS key name, as specified in the ESP-IDF documentation.
     static constexpr size_t kMaxConfigKeyNameLength = 15;
@@ -82,6 +83,8 @@
     static const Key kConfigKey_VendorName;
     static const Key kConfigKey_ProductId;
     static const Key kConfigKey_ProductName;
+    static const Key kConfigKey_SupportedCalTypes;
+    static const Key kConfigKey_SupportedLocaleSize;
 
     // CHIP Counter keys
     static const Key kCounterKey_RebootCount;
@@ -140,6 +143,31 @@
     return strcmp(Namespace, other.Namespace) == 0 && strcmp(Name, other.Name) == 0;
 }
 
+class ESP32Config::KeyAllocator
+{
+public:
+    static CHIP_ERROR Locale(char * key, size_t size, uint16_t index)
+    {
+        VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
+        return snprintf(key, size, "locale/%x", index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
+    }
+    static CHIP_ERROR FixedLabelCount(char * key, size_t size, uint16_t endpoint)
+    {
+        VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
+        return snprintf(key, size, "fl-sz/%x", endpoint) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
+    }
+    static CHIP_ERROR FixedLabelKey(char * key, size_t size, uint16_t endpoint, uint16_t index)
+    {
+        VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
+        return snprintf(key, size, "fl-k/%x/%x", endpoint, index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
+    }
+    static CHIP_ERROR FixedLabelValue(char * key, size_t size, uint16_t endpoint, uint16_t index)
+    {
+        VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
+        return snprintf(key, size, "fl-v/%x/%x", endpoint, index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
+    }
+};
+
 } // namespace Internal
 } // namespace DeviceLayer
 } // namespace chip
diff --git a/src/platform/ESP32/ESP32DeviceInfoProvider.cpp b/src/platform/ESP32/ESP32DeviceInfoProvider.cpp
new file mode 100644
index 0000000..248c204
--- /dev/null
+++ b/src/platform/ESP32/ESP32DeviceInfoProvider.cpp
@@ -0,0 +1,271 @@
+/*
+
+ *    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 <lib/core/CHIPTLV.h>
+#include <lib/support/CHIPMemString.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/DefaultStorageKeyAllocator.h>
+#include <platform/ESP32/ESP32Config.h>
+#include <platform/ESP32/ESP32DeviceInfoProvider.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#include <string.h>
+
+namespace chip {
+namespace DeviceLayer {
+
+namespace {
+constexpr TLV::Tag kLabelNameTag  = TLV::ContextTag(0);
+constexpr TLV::Tag kLabelValueTag = TLV::ContextTag(1);
+} // anonymous namespace
+
+using namespace Internal;
+
+ESP32DeviceInfoProvider & ESP32DeviceInfoProvider::GetDefaultInstance(void)
+{
+    static ESP32DeviceInfoProvider sInstance;
+    return sInstance;
+}
+
+DeviceInfoProvider::FixedLabelIterator * ESP32DeviceInfoProvider::IterateFixedLabel(EndpointId endpoint)
+{
+    return chip::Platform::New<FixedLabelIteratorImpl>(endpoint);
+}
+
+ESP32DeviceInfoProvider::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint) : mEndpoint(endpoint)
+{
+    mIndex = 0;
+}
+
+size_t ESP32DeviceInfoProvider::FixedLabelIteratorImpl::Count()
+{
+    char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
+    uint32_t count = 0;
+
+    VerifyOrReturnValue(ESP32Config::KeyAllocator::FixedLabelCount(keyBuf, sizeof(keyBuf), mEndpoint) == CHIP_NO_ERROR, 0);
+    ESP32Config::Key key(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
+    VerifyOrReturnValue(ESP32Config::ReadConfigValue(key, count) == CHIP_NO_ERROR, 0);
+    return count;
+}
+
+bool ESP32DeviceInfoProvider::FixedLabelIteratorImpl::Next(FixedLabelType & output)
+{
+    ChipLogDetail(DeviceLayer, "Get the fixed label with index:%u at endpoint:%d", static_cast<unsigned>(mIndex), mEndpoint);
+
+    char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
+    size_t keyOutLen   = 0;
+    size_t valueOutLen = 0;
+
+    memset(mFixedLabelNameBuf, 0, sizeof(mFixedLabelNameBuf));
+    memset(mFixedLabelValueBuf, 0, sizeof(mFixedLabelValueBuf));
+
+    VerifyOrReturnValue(ESP32Config::KeyAllocator::FixedLabelKey(keyBuf, sizeof(keyBuf), mEndpoint, mIndex) == CHIP_NO_ERROR,
+                        false);
+    ESP32Config::Key keyKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
+    VerifyOrReturnValue(
+        ESP32Config::ReadConfigValueStr(keyKey, mFixedLabelNameBuf, sizeof(mFixedLabelNameBuf), keyOutLen) == CHIP_NO_ERROR, false);
+
+    VerifyOrReturnValue(ESP32Config::KeyAllocator::FixedLabelValue(keyBuf, sizeof(keyBuf), mEndpoint, mIndex) == CHIP_NO_ERROR,
+                        false);
+    ESP32Config::Key valueKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
+    VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(valueKey, mFixedLabelValueBuf, sizeof(mFixedLabelValueBuf), valueOutLen) ==
+                            CHIP_NO_ERROR,
+                        false);
+
+    output.label = CharSpan::fromCharString(mFixedLabelNameBuf);
+    output.value = CharSpan::fromCharString(mFixedLabelValueBuf);
+    ChipLogDetail(DeviceLayer, "Fixed label with index:%u at endpoint:%d, %s:%s", static_cast<unsigned>(mIndex), mEndpoint,
+                  mFixedLabelNameBuf, mFixedLabelValueBuf);
+
+    mIndex++;
+    return true;
+}
+
+CHIP_ERROR ESP32DeviceInfoProvider::SetUserLabelLength(EndpointId endpoint, size_t val)
+{
+    DefaultStorageKeyAllocator keyAlloc;
+    return mStorage->SyncSetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, static_cast<uint16_t>(sizeof(val)));
+}
+
+CHIP_ERROR ESP32DeviceInfoProvider::GetUserLabelLength(EndpointId endpoint, size_t & val)
+{
+    DefaultStorageKeyAllocator keyAlloc;
+    uint16_t len = static_cast<uint16_t>(sizeof(val));
+    return mStorage->SyncGetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, len);
+}
+
+CHIP_ERROR ESP32DeviceInfoProvider::SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel)
+{
+    DefaultStorageKeyAllocator keyAlloc;
+    uint8_t buf[UserLabelTLVMaxSize()];
+    TLV::TLVWriter writer;
+    writer.Init(buf);
+
+    TLV::TLVType outerType;
+    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
+    ReturnErrorOnFailure(writer.PutString(kLabelNameTag, userLabel.label));
+    ReturnErrorOnFailure(writer.PutString(kLabelValueTag, userLabel.value));
+    ReturnErrorOnFailure(writer.EndContainer(outerType));
+
+    return mStorage->SyncSetKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index), buf,
+                                     static_cast<uint16_t>(writer.GetLengthWritten()));
+}
+
+CHIP_ERROR ESP32DeviceInfoProvider::DeleteUserLabelAt(EndpointId endpoint, size_t index)
+{
+    DefaultStorageKeyAllocator keyAlloc;
+    return mStorage->SyncDeleteKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index));
+}
+
+DeviceInfoProvider::UserLabelIterator * ESP32DeviceInfoProvider::IterateUserLabel(EndpointId endpoint)
+{
+    return chip::Platform::New<UserLabelIteratorImpl>(*this, endpoint);
+}
+
+ESP32DeviceInfoProvider::UserLabelIteratorImpl::UserLabelIteratorImpl(ESP32DeviceInfoProvider & provider, EndpointId endpoint) :
+    mProvider(provider), mEndpoint(endpoint)
+{
+    size_t total = 0;
+
+    ReturnOnFailure(mProvider.GetUserLabelLength(mEndpoint, total));
+    mTotal = total;
+    mIndex = 0;
+}
+
+bool ESP32DeviceInfoProvider::UserLabelIteratorImpl::Next(UserLabelType & output)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    VerifyOrReturnError(mIndex < mTotal, false);
+
+    DefaultStorageKeyAllocator keyAlloc;
+    uint8_t buf[UserLabelTLVMaxSize()];
+    uint16_t len = static_cast<uint16_t>(sizeof(buf));
+
+    err = mProvider.mStorage->SyncGetKeyValue(keyAlloc.UserLabelIndexKey(mEndpoint, mIndex), buf, len);
+    VerifyOrReturnError(err == CHIP_NO_ERROR, false);
+
+    TLV::ContiguousBufferTLVReader reader;
+    reader.Init(buf);
+    err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag());
+    VerifyOrReturnError(err == CHIP_NO_ERROR, false);
+
+    TLV::TLVType containerType;
+    VerifyOrReturnError(reader.EnterContainer(containerType) == CHIP_NO_ERROR, false);
+
+    chip::CharSpan label;
+    chip::CharSpan value;
+
+    VerifyOrReturnError(reader.Next(kLabelNameTag) == CHIP_NO_ERROR, false);
+    VerifyOrReturnError(reader.Get(label) == CHIP_NO_ERROR, false);
+
+    VerifyOrReturnError(reader.Next(kLabelValueTag) == CHIP_NO_ERROR, false);
+    VerifyOrReturnError(reader.Get(value) == CHIP_NO_ERROR, false);
+
+    VerifyOrReturnError(reader.VerifyEndOfContainer() == CHIP_NO_ERROR, false);
+    VerifyOrReturnError(reader.ExitContainer(containerType) == CHIP_NO_ERROR, false);
+
+    Platform::CopyString(mUserLabelNameBuf, label);
+    Platform::CopyString(mUserLabelValueBuf, value);
+
+    output.label = CharSpan::fromCharString(mUserLabelNameBuf);
+    output.value = CharSpan::fromCharString(mUserLabelValueBuf);
+
+    mIndex++;
+
+    return true;
+}
+
+DeviceInfoProvider::SupportedLocalesIterator * ESP32DeviceInfoProvider::IterateSupportedLocales()
+{
+    return chip::Platform::New<SupportedLocalesIteratorImpl>();
+}
+
+size_t ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Count()
+{
+    uint32_t count = 0;
+    CHIP_ERROR err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_SupportedLocaleSize, count);
+    if (err != CHIP_NO_ERROR)
+    {
+        return 0;
+    }
+    return count;
+}
+
+bool ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Next(CharSpan & output)
+{
+    char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
+    size_t keyOutLen = 0;
+    memset(mLocaleBuf, 0, sizeof(mLocaleBuf));
+
+    VerifyOrReturnValue(ESP32Config::KeyAllocator::Locale(keyBuf, sizeof(keyBuf), mIndex) == CHIP_NO_ERROR, false);
+    ESP32Config::Key keyKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
+    VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(keyKey, mLocaleBuf, sizeof(mLocaleBuf), keyOutLen) == CHIP_NO_ERROR, false);
+
+    output = CharSpan::fromCharString(mLocaleBuf);
+    mIndex++;
+    return true;
+}
+
+void ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Release()
+{
+    chip::Platform::Delete(this);
+}
+
+DeviceInfoProvider::SupportedCalendarTypesIterator * ESP32DeviceInfoProvider::IterateSupportedCalendarTypes()
+{
+    return chip::Platform::New<SupportedCalendarTypesIteratorImpl>();
+}
+
+ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::SupportedCalendarTypesIteratorImpl()
+{
+    CHIP_ERROR err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_SupportedCalTypes, mSupportedCalendarTypes);
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to read supported calendar types: %" CHIP_ERROR_FORMAT, err.Format());
+    }
+}
+
+size_t ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::Count()
+{
+    size_t count = 0;
+    for (uint8_t i = 0; i < to_underlying(CalendarType::kUnknownEnumValue); i++)
+    {
+        if (mSupportedCalendarTypes & (1 << i))
+        {
+            count++;
+        }
+    }
+    ChipLogDetail(DeviceLayer, "Supported calendar types count:%u", count);
+    return count;
+}
+
+bool ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::Next(CalendarType & output)
+{
+    while (mIndex < to_underlying(CalendarType::kUnknownEnumValue))
+    {
+        if (mSupportedCalendarTypes & (1 << mIndex))
+        {
+            output = static_cast<CalendarType>(mIndex);
+            mIndex++;
+            return true;
+        }
+        mIndex++;
+    }
+    return false;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/ESP32/ESP32DeviceInfoProvider.h b/src/platform/ESP32/ESP32DeviceInfoProvider.h
new file mode 100644
index 0000000..d1870ea
--- /dev/null
+++ b/src/platform/ESP32/ESP32DeviceInfoProvider.h
@@ -0,0 +1,108 @@
+/*
+ *
+ *    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 <lib/support/EnforceFormat.h>
+#include <platform/DeviceInfoProvider.h>
+
+namespace chip {
+namespace DeviceLayer {
+
+class ESP32DeviceInfoProvider : public DeviceInfoProvider
+{
+public:
+    ESP32DeviceInfoProvider() = default;
+    ~ESP32DeviceInfoProvider() override {}
+
+    // Iterators
+    FixedLabelIterator * IterateFixedLabel(EndpointId endpoint) override;
+    UserLabelIterator * IterateUserLabel(EndpointId endpoint) override;
+    SupportedLocalesIterator * IterateSupportedLocales() override;
+    SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() override;
+
+    static ESP32DeviceInfoProvider & GetDefaultInstance();
+
+protected:
+    class FixedLabelIteratorImpl : public FixedLabelIterator
+    {
+    public:
+        FixedLabelIteratorImpl(EndpointId endpoint);
+        size_t Count() override;
+        bool Next(FixedLabelType & output) override;
+        void Release() override { chip::Platform::Delete(this); }
+
+    private:
+        EndpointId mEndpoint = 0;
+        size_t mIndex        = 0;
+        char mFixedLabelNameBuf[kMaxLabelNameLength + 1];
+        char mFixedLabelValueBuf[kMaxLabelValueLength + 1];
+    };
+
+    class UserLabelIteratorImpl : public UserLabelIterator
+    {
+    public:
+        UserLabelIteratorImpl(ESP32DeviceInfoProvider & provider, EndpointId endpoint);
+        size_t Count() override { return mTotal; }
+        bool Next(UserLabelType & output) override;
+        void Release() override { chip::Platform::Delete(this); }
+
+    private:
+        ESP32DeviceInfoProvider & mProvider;
+        EndpointId mEndpoint = 0;
+        size_t mIndex        = 0;
+        size_t mTotal        = 0;
+        char mUserLabelNameBuf[kMaxLabelNameLength + 1];
+        char mUserLabelValueBuf[kMaxLabelValueLength + 1];
+    };
+
+    class SupportedLocalesIteratorImpl : public SupportedLocalesIterator
+    {
+    public:
+        SupportedLocalesIteratorImpl() = default;
+        size_t Count() override;
+        bool Next(CharSpan & output) override;
+        void Release() override;
+
+    private:
+        size_t mIndex = 0;
+        char mLocaleBuf[kMaxActiveLocaleLength + 1];
+    };
+
+    class SupportedCalendarTypesIteratorImpl : public SupportedCalendarTypesIterator
+    {
+    public:
+        SupportedCalendarTypesIteratorImpl();
+        size_t Count() override;
+        bool Next(CalendarType & output) override;
+        void Release() override { chip::Platform::Delete(this); }
+
+    private:
+        size_t mIndex                    = 0;
+        uint32_t mSupportedCalendarTypes = 0;
+    };
+
+    CHIP_ERROR SetUserLabelLength(EndpointId endpoint, size_t val) override;
+    CHIP_ERROR GetUserLabelLength(EndpointId endpoint, size_t & val) override;
+    CHIP_ERROR SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) override;
+    CHIP_ERROR DeleteUserLabelAt(EndpointId endpoint, size_t index) override;
+
+private:
+    static constexpr size_t UserLabelTLVMaxSize() { return TLV::EstimateStructOverhead(kMaxLabelNameLength, kMaxLabelValueLength); }
+};
+
+} // namespace DeviceLayer
+} // namespace chip