[K32W0] SDK 2.6.13 additional changes (#31382)

* [K32W] Fix a corner case when switching the TLV processors

After the current block is processed, if the block size is 0, it means
that the processed data was a multiple of received BDX block size (e.g.
8 blocks of 1024 bytes were transferred). After state for selecting next
processor is reset, a request for fetching next data must be sent.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W] Make Validate public

Change access modifier of Validate to public, to be used by K32W0
for factory data validation after factory data OTA.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Add CRC validation during factory data OTA

After factory data is copied into internal flash, call Validate to ensure
the CRC of factory data matches the CRC in the header. If the check fails,
then OTA is aborted and factory data is restored to previous version.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Add additional check for provider pointer

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Change root node revision to 2

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W] Expose SearchForId in factory data provider public API

Removed additional checks on tags with the assumption that factory data is
strictly checked at manufacturing time.
Applications can now use the public API to search the factory data section
for an id, e.g. in the case of custom factory data provider, where the app
has additional factory data information besides the default one.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Refactor custom factory data provider

The example now leverages the actual factory data provider API to
search the factory data section for some custom ids.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W] Add platform support for Product Appearance

Implement GetProductFinish and GetProductPrimaryColor defined in DeviceInstanceInfoProvider.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W] Remove maxLengths array

This array was used to store the maximum length of factory data fields.
It's no longer used, with the assumption that the factory data is strictly
checked in manufacturing.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Remove usage of maxLength array

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] remove unused code in LowPowerHook.cpp file

* [K32W0] use Encoding::HexToBytes to parse the ota encryption key

* [K32W0] remove extra PWR_DisallowDeviceToSleep() which will cause unsleep after commissioning

* [K32W] Revert removal of disallow to sleep and enclose it in specific tag

Only call disallow to sleep when the platform is K32W1.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Update reference app readme files

This is a minor improvement to the building instructions.
It aims to clarify the usage of west SDK or package SDK.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W0] Fix ICD parameters

Name of the ICD parameters were updated according with the latest stack updates.

Signed-off-by: Andrei Menzopol <andrei.menzopol@nxp.com>

* Restyled by clang-format

* Restyled by gn

* Restyled by prettier-markdown

* [K32W0] Fix gn check error

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* Restyled by gn

* [K32W1] Fix gn check errors

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* Restyled by gn

* [K32W1] Fix another gn error

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* Restyled by gn

* [K32W] Send a report before resetting the device during OTA

State-transition event from Downloading to Applying was not successfully sent
to a subscriber during OTA because the device would reset before actually sending
the ReportData message.

Added an explicit call to handle server shutting down, which will sync send all events.

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* Restyled by clang-format

* [K32W0] Remove deprecated dependency

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* [K32W1] Remove deprecated dependency

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>

* Restyled by gn

---------

Signed-off-by: marius-alex-tache <marius.tache@nxp.com>
Signed-off-by: Andrei Menzopol <andrei.menzopol@nxp.com>
Co-authored-by: Damien Vagner <damien.vagner@nxp.com>
Co-authored-by: tanyue518 <ethan.tan@nxp.com>
Co-authored-by: Ethan Tan <nxf42555@lsvm11u0000160.swis.ap-northeast-2.aws.nxp.com>
Co-authored-by: Andrei Menzopol <andrei.menzopol@nxp.com>
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter
index 6065ce3..6023f53 100644
--- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter
+++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter
@@ -1631,7 +1631,7 @@
 }
 
 endpoint 0 {
-  device type ma_rootdevice = 22, version 1;
+  device type ma_rootdevice = 22, version 2;
 
   binding cluster OtaSoftwareUpdateProvider;
 
diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap
index b37968d..8c58d93 100644
--- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap
+++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap
@@ -51,7 +51,7 @@
         }
       ],
       "deviceVersions": [
-        1
+        2
       ],
       "deviceIdentifiers": [
         22
@@ -4748,4 +4748,4 @@
     }
   ],
   "log": []
-}
\ No newline at end of file
+}
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn
index 36f52d9..cc87b4f 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn
+++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn
@@ -93,10 +93,7 @@
       "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h",
     ]
 
-    defines = [
-      "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1",
-      "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3",
-    ]
+    defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ]
   }
 
   deps = [
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md
index f616ddf..27ae15b 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md
+++ b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md
@@ -177,56 +177,58 @@
 In order to build the Project CHIP example, we recommend using a Linux
 distribution (the demo-application was compiled on Ubuntu 20.04).
 
--   Start building the application either with Secure Element or without, SDK is
-    downloaded with west tool.
+Activate the Matter environment:
 
-    -   without Secure Element
+```bash
+user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
+```
 
-    ```
-    user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
+To bring the SDK in the environment, the user can:
+
+-   download it with west tool, in which case it will be handled automatically
+    by gn:
+
+    ```bash
     user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
     user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml
     user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update
     ```
 
-    In case there are local modification to the already installed git NXP SDK:
-    Use the below west `forall` command instead of the west init command to
-    reset the west workspace. Warning: all local changes will be lost after
+    In case there are local modification to the already installed github NXP
+    SDK, use the below `west forall` command instead of the `west init` command
+    to reset the west workspace. Warning: all local changes will be lost after
     running this command.
 
     ```bash
     user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
-    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a
     ```
 
-    Build the application
-
-    Prior to building, the user can specify a custom `SDK` path by setting
-    `NXP_K32W0_SDK_ROOT`:
+-   set up a custom path to the SDK, in which case
+    `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen`
+    command:
 
     ```
-    user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core
+    user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK
     ```
 
-    If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default
-    to the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`.
+Start building the application:
 
-    ```
-    user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0
-    user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true"
-    user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug
-    ```
+```bash
+user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true"
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug
+```
 
-    -   with Secure element Exactly the same steps as above but set
-        chip_with_se05x=1 in the gn command and add argument
-        chip_enable_ota_requestor=false
+To build with Secure Element, follow the same steps as above but set
+`chip_with_se05x=1 chip_enable_ota_requestor=false` in the `gn gen` command.
 
-Note that option chip_enable_ota_requestor=false are required for building with
-Secure Element. These can be changed if building without Secure Element
+Note that option `chip_enable_ota_requestor=false` is required for building with
+Secure Element due to flash constraints.
 
 -   K32W041AM flavor
 
-    Exactly the same steps as above but set argument build_for_k32w041am=1 in
+    Exactly the same steps as above but set argument `build_for_k32w041am=1` in
     the gn command.
 
 Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
index b48b97c..72f9487 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
+++ b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
@@ -48,13 +48,6 @@
 #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0
 #endif
 
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS
-// Set to 3: default number of custom Ids from CustomFactoryDataProvider example
-#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3
-#endif
-#endif
-
 // VID/PID for product => will be used by Basic Information Cluster
 #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037
 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp
index 484ddce..5c942db 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp
+++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp
@@ -85,7 +85,10 @@
 
 AppTask AppTask::sAppTask;
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-static AppTask::FactoryDataProvider sFactoryDataProvider;
+static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider;
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider;
+#endif
 #endif
 
 static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop,
@@ -199,6 +202,9 @@
     SetDeviceInstanceInfoProvider(&sFactoryDataProvider);
     SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider);
     SetCommissionableDataProvider(&sFactoryDataProvider);
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+    sCustomFactoryDataProvider.ParseFunctionExample();
+#endif
 #else
 #ifdef ENABLE_HSM_DEVICE_ATTESTATION
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider());
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h
index 58effbd..867a496 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h
+++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h
@@ -50,15 +50,6 @@
 class AppTask
 {
 public:
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-    using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider;
-#else
-    using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl;
-#endif
-#endif
-
-public:
     CHIP_ERROR StartAppTask();
     static void AppTaskMain(void * pvParameter);
 
diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn
index a71bf63..93bf1dc 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn
+++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn
@@ -95,10 +95,7 @@
       "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h",
     ]
 
-    defines = [
-      "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1",
-      "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3",
-    ]
+    defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ]
   }
 
   deps = [
diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md
index b43a086..3194d71 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/README.md
+++ b/examples/lighting-app/nxp/k32w/k32w0/README.md
@@ -192,58 +192,58 @@
 In order to build the Project CHIP example, we recommend using a Linux
 distribution (the demo-application was compiled on Ubuntu 20.04).
 
--   Start building the application either with Secure Element or without, SDK is
-    downloaded with west tool.
-    -   without Secure Element
-
-```
-user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update
-```
-
-In case there are local modification to the already installed git NXP SDK: Use
-the below west `forall` command instead of the west init command to reset the
-west workspace. Warning: all local changes will be lost after running this
-command.
+Activate the Matter environment:
 
 ```bash
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a
+user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
 ```
 
-Build the application
+To bring the SDK in the environment, the user can:
 
-Prior to building, the user can specify a custom `SDK` path by setting
-`NXP_K32W0_SDK_ROOT`:
+-   download it with west tool, in which case it will be handled automatically
+    by gn:
 
-```
-user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core
-```
+    ```bash
+    user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update
+    ```
 
-If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default to
-the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`.
+    In case there are local modification to the already installed github NXP
+    SDK, use the below `west forall` command instead of the `west init` command
+    to reset the west workspace. Warning: all local changes will be lost after
+    running this command.
 
-```
+    ```bash
+    user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a
+    ```
+
+-   set up a custom path to the SDK, in which case
+    `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen`
+    command:
+
+    ```
+    user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK
+    ```
+
+Start building the application:
+
+```bash
 user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w0
 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true"
 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ ninja -C out/debug
 ```
 
-    -   with Secure element
+To build with Secure Element, follow the same steps as above but set
+`chip_with_se05x=1 chip_enable_ota_requestor=false` in the `gn gen` command.
 
-```
-        Exactly the same steps as above but set chip_with_se05x=1 in the gn command
-        and add argument chip_enable_ota_requestor=false
-```
-
-Note that option chip_enable_ota_requestor=false are required for building with
-Secure Element. These can be changed if building without Secure Element
+Note that option `chip_enable_ota_requestor=false` is required for building with
+Secure Element due to flash constraints.
 
 -   K32W041AM flavor
 
-    Exactly the same steps as above but set argument build_for_k32w041am=1 in
+    Exactly the same steps as above but set argument `build_for_k32w041am=1` in
     the gn command.
 
 Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the
diff --git a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
index 10019a4..946d457 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
+++ b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
@@ -48,13 +48,6 @@
 #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0
 #endif
 
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS
-// Set to 3: default number of custom Ids from CustomFactoryDataProvider example
-#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3
-#endif
-#endif
-
 // VID/PID for product => will be used by Basic Information Cluster
 #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037
 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
index e63c35a..557293f 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
+++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
@@ -85,7 +85,10 @@
 
 AppTask AppTask::sAppTask;
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-static AppTask::FactoryDataProvider sFactoryDataProvider;
+static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider;
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider;
+#endif
 #endif
 
 // This key is for testing/certification only and should not be used in production devices.
@@ -190,6 +193,9 @@
     SetDeviceInstanceInfoProvider(&sFactoryDataProvider);
     SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider);
     SetCommissionableDataProvider(&sFactoryDataProvider);
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+    sCustomFactoryDataProvider.ParseFunctionExample();
+#endif
 #else
 #ifdef ENABLE_HSM_DEVICE_ATTESTATION
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider());
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
index 83dfd33..9590734 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
+++ b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
@@ -50,15 +50,6 @@
 class AppTask
 {
 public:
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-    using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider;
-#else
-    using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl;
-#endif
-#endif
-
-public:
     CHIP_ERROR StartAppTask();
     static void AppTaskMain(void * pvParameter);
 
diff --git a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn
index fd095a2..a7643a9 100644
--- a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn
+++ b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn
@@ -82,6 +82,8 @@
     "main/main.cpp",
   ]
 
+  public = [ "${chip_root}/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h" ]
+
   deps = [
     ":sdk",
     "${chip_root}/examples/common/QRCode",
diff --git a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn
index 0b75258..c755514 100644
--- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn
+++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn
@@ -92,10 +92,7 @@
       "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h",
     ]
 
-    defines = [
-      "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1",
-      "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3",
-    ]
+    defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ]
   }
 
   deps = [
diff --git a/examples/lock-app/nxp/k32w/k32w0/README.md b/examples/lock-app/nxp/k32w/k32w0/README.md
index b5fec55..4992090 100644
--- a/examples/lock-app/nxp/k32w/k32w0/README.md
+++ b/examples/lock-app/nxp/k32w/k32w0/README.md
@@ -173,59 +173,67 @@
 In order to build the Project CHIP example, we recommend using a Linux
 distribution (the demo-application was compiled on Ubuntu 20.04).
 
--   Start building the application either with Secure Element or without, SDK is
-    downloaded with west tool.
-
-    -   without Secure Element
-
-```
-user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update
-```
-
-In case there are local modification to the already installed git NXP SDK: Use
-the below west `forall` command instead of the west init command to reset the
-west workspace. Warning: all local changes will be lost after running this
-command.
+Activate the Matter environment:
 
 ```bash
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
-user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a
+user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh
 ```
 
-Build the application
+To bring the SDK in the environment, the user can:
 
-Prior to building, the user can specify a custom `SDK` path by setting
-`NXP_K32W0_SDK_ROOT`:
+-   download it with west tool, in which case it will be handled automatically
+    by gn:
 
-```
-user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core
-```
+    ```bash
+    user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update
+    ```
 
-If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default to
-the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`.
+    In case there are local modification to the already installed github NXP
+    SDK, use the below `west forall` command instead of the `west init` command
+    to reset the west workspace. Warning: all local changes will be lost after
+    running this command.
 
-```
+    ```bash
+    user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo
+    user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a
+    ```
+
+-   set up a custom path to the SDK, in which case
+    `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen`
+    command:
+
+    ```
+    user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK
+    ```
+
+Start building the application:
+
+```bash
 user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lock-app/nxp/k32w/k32w0
 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true"
 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ ninja -C out/debug
 ```
 
-    -   with Secure element
-        Exactly the same steps as above but set chip_with_se05x=1 in the gn command.
+To build with Secure Element, follow the same steps as above but set
+`chip_with_se05x=1` in the `gn gen` command.
+
+-   K32W041AM flavor
+
+    Exactly the same steps as above but set argument `build_for_k32w041am=1` in
+    the gn command.
 
 Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the
-build argument (chip_with_OM15082) inside the gn build instruction should be set
-to zero. The argument chip_with_OM15082 is set to zero by default.
+build argument (`chip_with_OM15082`) inside the gn build instruction should be
+set to zero. The argument `chip_with_OM15082` is set to zero by default.
 
-In case that Openthread CLI is needed, chip_with_ot_cli build argument must be
+In case that Openthread CLI is needed, `chip_with_ot_cli` build argument must be
 set to 1.
 
 In case the board doesn't have 32KHz crystal fitted, one can use the 32KHz free
-running oscillator as a clock source. In this case one must set the use_fro_32k
-argument to 1.
+running oscillator as a clock source. In this case one must set the
+`use_fro_32k` argument to 1.
 
 In case signing errors are encountered when running the "sign_images.sh" script
 (run automatically) install the recommanded packages (python version > 3, pip3,
diff --git a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
index c74714b..4359887 100644
--- a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
+++ b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
@@ -48,13 +48,6 @@
 #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0
 #endif
 
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS
-// Set to 3: default number of custom Ids from CustomFactoryDataProvider example
-#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3
-#endif
-#endif
-
 // VID/PID for product => will be used by Basic Information Cluster
 #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037
 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220
diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp
index fff749b..1305697 100644
--- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp
+++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp
@@ -71,7 +71,10 @@
 
 AppTask AppTask::sAppTask;
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-static AppTask::FactoryDataProvider sFactoryDataProvider;
+static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider;
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider;
+#endif
 #endif
 
 CHIP_ERROR AppTask::StartAppTask()
@@ -102,6 +105,9 @@
     SetDeviceInstanceInfoProvider(&sFactoryDataProvider);
     SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider);
     SetCommissionableDataProvider(&sFactoryDataProvider);
+#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
+    sCustomFactoryDataProvider.ParseFunctionExample();
+#endif
 #else
 #ifdef ENABLE_HSM_DEVICE_ATTESTATION
     SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider());
diff --git a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h
index cbaa575..1addd92 100644
--- a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h
+++ b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h
@@ -41,15 +41,6 @@
 class AppTask
 {
 public:
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-    using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider;
-#else
-    using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl;
-#endif
-#endif
-
-public:
     CHIP_ERROR StartAppTask();
     static void AppTaskMain(void * pvParameter);
 
diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp
index 18e8095..7f2f6d9 100644
--- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp
+++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp
@@ -24,21 +24,10 @@
 static constexpr size_t kMaxLengthCustomId2 = 50;
 static constexpr size_t kMaxLengthCustomId3 = 100;
 
-CustomFactoryDataProvider & CustomFactoryDataProvider::GetDefaultInstance()
+CustomFactoryDataProvider::CustomFactoryDataProvider()
 {
-    static CustomFactoryDataProvider sInstance;
-    return sInstance;
-}
-
-CHIP_ERROR CustomFactoryDataProvider::SetCustomIds()
-{
-    static_assert(CustomFactoryIds::kCustomMaxId == FactoryDataProvider::kNumberOfIds,
-                  "kNumberOfIds is computed based on CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS.");
-    maxLengths[CustomFactoryIds::kCustomId1] = kMaxLengthCustomId1;
-    maxLengths[CustomFactoryIds::kCustomId2] = kMaxLengthCustomId2;
-    maxLengths[CustomFactoryIds::kCustomId3] = kMaxLengthCustomId3;
-
-    return CHIP_NO_ERROR;
+    // Custom ids should be from a range that does not overlap with the standard factory data range.
+    static_assert((uint16_t) CustomFactoryIds::kCustomId1 >= (uint16_t) FactoryDataProvider::FactoryDataId::kMaxId);
 }
 
 CHIP_ERROR CustomFactoryDataProvider::ParseFunctionExample()
@@ -49,7 +38,9 @@
     uint16_t userDataSize = 0;
     // A user can use FactoryDataProvider::SearchForId to read an id from internal
     // flash factory data section.
-    ReturnErrorOnFailure(SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize));
+    auto * provider = static_cast<FactoryDataProvider *>(DeviceLayer::GetDeviceInstanceInfoProvider());
+    ReturnErrorOnFailure((provider != nullptr) ? CHIP_NO_ERROR : CHIP_ERROR_INVALID_ADDRESS);
+    ReturnErrorOnFailure(provider->SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize));
 
     // Data should now be ready for custom parsing.
 
diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h
index 9edd603..dfb722d 100644
--- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h
+++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h
@@ -27,26 +27,21 @@
  *        provider based on this example.
  */
 
-class CustomFactoryDataProvider : public FactoryDataProviderImpl
+class CustomFactoryDataProvider
 {
 public:
-    /* Custom IDs should start from FactoryDataId::kMaxId, which is
+    /* Custom IDs should start from at least FactoryDataId::kMaxId, which is
      * the next available valid ID. Last default ID is kMaxId - 1.
      */
     enum CustomFactoryIds
     {
-        kCustomId1 = FactoryDataId::kMaxId,
+        kCustomId1 = 200, // Random id that is greater than FactoryDataId::kMaxId.
         kCustomId2,
         kCustomId3,
         kCustomMaxId
     };
 
-    static CustomFactoryDataProvider & GetDefaultInstance();
-
-    CustomFactoryDataProvider() {}
-
-    /* SetCustomIds() must be implemented in order to define custom IDs. */
-    CHIP_ERROR SetCustomIds() override;
+    CustomFactoryDataProvider();
 
     /* Declare here custom functions to be implemented. */
     CHIP_ERROR ParseFunctionExample();
diff --git a/examples/platform/nxp/k32w/k32w0/common/README.md b/examples/platform/nxp/k32w/k32w0/common/README.md
index 459f62f..59347d6 100644
--- a/examples/platform/nxp/k32w/k32w0/common/README.md
+++ b/examples/platform/nxp/k32w/k32w0/common/README.md
@@ -12,10 +12,11 @@
 -   DeviceAttestationCredentialsProvider
 -   DeviceInstanceInfoProvider
 
-A user can inherit `FactoryDataProviderImpl` to provide additional functionality
-(such as parsing custom factory data fields) that is customer specific.
+A user can use `FactoryDataProvider::SearchForId` API to extract information
+about custom factory data ids.
 
-What **shall** be done to enable usage of a custom factory provider:
+What **shall** be done to enable usage of a custom factory provider in the
+reference app:
 
 -   Set `use_custom_factory_provider=1`. This option is only available when
     factory data is used (`chip_with_factory_data=1`). An assert will be raised
@@ -33,28 +34,15 @@
 
       defines = [
         "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1",
-        "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3"
       ]
     }
     ```
 
-    Note that new flags were introduced:
+Note that new flags were introduced:
 
-    -   `CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER`: select between using
-        `FactoryDataProviderImpl` or `CustomFactoryDataProvider` when
-        registering the provider.
-    -   `CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS`: set the number of
-        custom IDs (which are different than the default IDs). If this macro is
-        not correctly set, compilation should fail.
+-   `CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER`: add custom factory data related
+    code in reference app.
 
--   The default IDs are validated directly in `SearchForId`, but custom IDs
-    should set their maximum lengths through `SetCustomIds` method.
--   `FactoryDataProvider::kNumberOfIds` is computed at compile time and should
-    represent the number of IDs (custom + default). Custom IDs should start from
-    `FactoryDataId::kMaxId`, which is the next valid ID. IDs
-    `[1, FactoryDataId::kMaxId - 1]` are reserved for default factory data IDs.
-
-Please refer to `CustomFactoryDataProvider` for a minimal example of a custom
-factory data provider and note that its implementation is just an example of how
-to integrate a custom provider into the application, while still using the
-default implementation provided by `FactoryDataProviderImpl`.
+Please refer to `CustomFactoryDataProvider` for a minimal example of leveraging
+the standard factory data provider to parse custom factory data information.
+Real applications could use the public API of `FactoryDataProvider` directly.
diff --git a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
index 5d20035..d6aa5f2 100644
--- a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
+++ b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp
@@ -1174,9 +1174,14 @@
 
     if (pConnectionEvent->eventType == gConnEvtConnected_c)
     {
+#if CHIP_DEVICE_K32W1
 #if defined(chip_with_low_power) && (chip_with_low_power == 1)
+        /* Disallow must be called here for K32W1, otherwise an assert will be reached.
+         * Disclaimer: this is a workaround until a better cross platform solution is found. */
         PWR_DisallowDeviceToSleep();
 #endif
+#endif
+
 #if CHIP_DEVICE_CONFIG_BLE_SET_PHY_2M_REQ
         ChipLogProgress(DeviceLayer, "BLE K32W: Trying to set the PHY to 2M");
 
diff --git a/src/platform/nxp/k32w/common/FactoryDataProvider.cpp b/src/platform/nxp/k32w/common/FactoryDataProvider.cpp
index 315811c..1770cf2 100644
--- a/src/platform/nxp/k32w/common/FactoryDataProvider.cpp
+++ b/src/platform/nxp/k32w/common/FactoryDataProvider.cpp
@@ -44,31 +44,6 @@
 uint32_t FactoryDataProvider::kFactoryDataSize         = (uint32_t) __MATTER_FACTORY_DATA_SIZE;
 uint32_t FactoryDataProvider::kFactoryDataPayloadStart = kFactoryDataStart + sizeof(FactoryDataProvider::Header);
 
-FactoryDataProvider::FactoryDataProvider()
-{
-    maxLengths[FactoryDataId::kVerifierId]           = kSpake2pSerializedVerifier_MaxBase64Len;
-    maxLengths[FactoryDataId::kSaltId]               = kSpake2pSalt_MaxBase64Len;
-    maxLengths[FactoryDataId::kIcId]                 = sizeof(uint32_t);
-    maxLengths[FactoryDataId::kDacPrivateKeyId]      = Crypto::kP256_PrivateKey_Length;
-    maxLengths[FactoryDataId::kDacCertificateId]     = Credentials::kMaxDERCertLength;
-    maxLengths[FactoryDataId::kPaiCertificateId]     = Credentials::kMaxDERCertLength;
-    maxLengths[FactoryDataId::kDiscriminatorId]      = sizeof(uint32_t);
-    maxLengths[FactoryDataId::kSetupPasscodeId]      = sizeof(uint32_t);
-    maxLengths[FactoryDataId::kVidId]                = sizeof(uint16_t);
-    maxLengths[FactoryDataId::kPidId]                = sizeof(uint16_t);
-    maxLengths[FactoryDataId::kCertDeclarationId]    = Credentials::kMaxCMSSignedCDMessage;
-    maxLengths[FactoryDataId::kVendorNameId]         = ConfigurationManager::kMaxVendorNameLength;
-    maxLengths[FactoryDataId::kProductNameId]        = ConfigurationManager::kMaxProductNameLength;
-    maxLengths[FactoryDataId::kSerialNumberId]       = ConfigurationManager::kMaxSerialNumberLength;
-    maxLengths[FactoryDataId::kManufacturingDateId]  = ConfigurationManager::kMaxManufacturingDateLength;
-    maxLengths[FactoryDataId::kHardwareVersionId]    = sizeof(uint16_t);
-    maxLengths[FactoryDataId::kHardwareVersionStrId] = ConfigurationManager::kMaxHardwareVersionStringLength;
-    maxLengths[FactoryDataId::kUniqueId]             = ConfigurationManager::kMaxUniqueIDLength;
-    maxLengths[FactoryDataId::kPartNumber]           = ConfigurationManager::kMaxPartNumberLength;
-    maxLengths[FactoryDataId::kProductURL]           = ConfigurationManager::kMaxProductURLLength;
-    maxLengths[FactoryDataId::kProductLabel]         = ConfigurationManager::kMaxProductLabelLength;
-}
-
 FactoryDataProvider::~FactoryDataProvider() {}
 
 CHIP_ERROR FactoryDataProvider::Validate()
@@ -97,12 +72,6 @@
 
         if (searchedType == type)
         {
-            if ((type >= FactoryDataProvider::kNumberOfIds) || (length > maxLengths[type]))
-            {
-                ChipLogError(DeviceLayer, "Failed validity check for factory data with: id=%d, length=%d", type, length);
-                break;
-            }
-
             ReturnErrorCodeIf(bufLength < length, CHIP_ERROR_BUFFER_TOO_SMALL);
             memcpy(pBuf, (void *) (addr + kValueOffset), length);
 
@@ -367,5 +336,29 @@
     return err;
 }
 
+CHIP_ERROR FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
+{
+    uint8_t productFinish;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductFinish, &productFinish, sizeof(productFinish), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(productFinish);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
+{
+    uint8_t color;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductPrimaryColor, &color, sizeof(color), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(color);
+
+    return CHIP_NO_ERROR;
+}
+
 } // namespace DeviceLayer
 } // namespace chip
diff --git a/src/platform/nxp/k32w/common/FactoryDataProvider.h b/src/platform/nxp/k32w/common/FactoryDataProvider.h
index 99b9a1e..2bad3e7 100644
--- a/src/platform/nxp/k32w/common/FactoryDataProvider.h
+++ b/src/platform/nxp/k32w/common/FactoryDataProvider.h
@@ -88,17 +88,11 @@
         kPartNumber,
         kProductURL,
         kProductLabel,
+        kProductFinish,
+        kProductPrimaryColor,
         kMaxId
     };
 
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-#if !CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS
-#error "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS must be > 0 if custom provider is enabled."
-#endif
-    static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId + CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS;
-#else
-    static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId;
-#endif
     static uint32_t kFactoryDataStart;
     static uint32_t kFactoryDataSize;
     static uint32_t kFactoryDataPayloadStart;
@@ -107,11 +101,13 @@
     static constexpr uint32_t kHashLen      = 4;
     static constexpr size_t kHashId         = 0xCE47BA5E;
 
-    FactoryDataProvider();
     virtual ~FactoryDataProvider();
 
     virtual CHIP_ERROR Init()                                                                          = 0;
     virtual CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) = 0;
+    CHIP_ERROR Validate();
+
+    CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * offset = nullptr);
 
     // ===== Members functions that implement the CommissionableDataProvider
     CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
@@ -142,12 +138,10 @@
     CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
     CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
     CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
+    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
 
 protected:
-    CHIP_ERROR Validate();
-    CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * offset = nullptr);
-
-    uint16_t maxLengths[kNumberOfIds];
     Header mHeader;
 };
 
diff --git a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
index c80bf64..946c0c3 100644
--- a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
+++ b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp
@@ -148,6 +148,16 @@
             mAccumulator.Init(sizeof(OTATlvHeader));
 
             mCurrentProcessor = nullptr;
+
+            // If the block size is 0, it means that the processed data was a multiple of
+            // received BDX block size (e.g. 8 blocks of 1024 bytes were transferred).
+            // After state for selecting next processor is reset, a request for fetching next
+            // data must be sent.
+            if (block.size() == 0)
+            {
+                status = CHIP_NO_ERROR;
+                break;
+            }
         }
         else
         {
@@ -380,7 +390,11 @@
     // queued actions, e.g. sending events to a subscription
     SystemLayer().StartTimer(
         chip::System::Clock::Milliseconds32(CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY),
-        [](chip::System::Layer *, void *) { OtaHookReset(); }, nullptr);
+        [](chip::System::Layer *, void *) {
+            PlatformMgr().HandleServerShuttingDown();
+            OtaHookReset();
+        },
+        nullptr);
 }
 
 CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
diff --git a/src/platform/nxp/k32w/common/OTATlvProcessor.cpp b/src/platform/nxp/k32w/common/OTATlvProcessor.cpp
index 7571e69..d9d2ccb 100644
--- a/src/platform/nxp/k32w/common/OTATlvProcessor.cpp
+++ b/src/platform/nxp/k32w/common/OTATlvProcessor.cpp
@@ -45,7 +45,7 @@
         if (mProcessedLength == mLength)
         {
             status = ExitAction();
-            if (!IsError(status) && (block.size() > 0))
+            if (!IsError(status))
             {
                 // If current block was processed fully and the block still contains data, it
                 // means that the block contains another TLV's data and the current processor
@@ -106,7 +106,7 @@
 CHIP_ERROR OTATlvProcessor::vOtaProcessInternalEncryption(MutableByteSpan & block)
 {
     uint8_t iv[16];
-    uint8_t key[16];
+    uint8_t key[kOTAEncryptionKeyLength];
     uint8_t dataOut[16] = { 0 };
     uint32_t u32IVCount;
     uint32_t Offset = 0;
@@ -124,18 +124,13 @@
     iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff);
     iv[15] = (uint8_t) (u32IVCount & 0xff);
 
-    size_t len = strlen(OTA_ENCRYPTION_KEY);
-
-    if (len != 32)
+    if (Encoding::HexToBytes(OTA_ENCRYPTION_KEY, strlen(OTA_ENCRYPTION_KEY), key, kOTAEncryptionKeyLength) !=
+        kOTAEncryptionKeyLength)
     {
-        return CHIP_ERROR_INVALID_ARGUMENT;
+        // Failed to convert the OTAEncryptionKey string to octstr type value
+        return CHIP_ERROR_INVALID_STRING_LENGTH;
     }
 
-    for (size_t i = 0; i < len; i += 2)
-    {
-        char hex[3] = { OTA_ENCRYPTION_KEY[i], OTA_ENCRYPTION_KEY[i + 1], '\0' };
-        key[i / 2]  = (uint8_t) strtol(hex, NULL, 16);
-    }
     ByteSpan KEY = ByteSpan(key);
     Encoding::LittleEndian::Reader reader_key(KEY.data(), KEY.size());
     ReturnErrorOnFailure(reader_key.Read32(&sKey.u32register0)
diff --git a/src/platform/nxp/k32w/common/OTATlvProcessor.h b/src/platform/nxp/k32w/common/OTATlvProcessor.h
index e412e1c..13a2df1 100644
--- a/src/platform/nxp/k32w/common/OTATlvProcessor.h
+++ b/src/platform/nxp/k32w/common/OTATlvProcessor.h
@@ -127,6 +127,8 @@
 #if OTA_ENCRYPTION_ENABLE
     /*ota decryption*/
     uint32_t mIVOffset = 0;
+    /* Expected byte size of the OTAEncryptionKeyLength */
+    static constexpr size_t kOTAEncryptionKeyLength = 16;
 #endif
     uint32_t mLength                             = 0;
     uint32_t mProcessedLength                    = 0;
diff --git a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h
index 2f582b2..8300240 100644
--- a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h
+++ b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h
@@ -79,13 +79,13 @@
 
 #if NXP_ICD_ENABLED
 
-#ifndef CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC
-#define CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC NXP_IDLE_MODE_INTERVAL
-#endif // CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC
+#ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC
+#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_INTERVAL
+#endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC
 
-#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS
-#define CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS NXP_ACTIVE_MODE_INTERVAL
-#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS
+#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS
+#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_INTERVAL
+#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS
 
 #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS
 #define CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS NXP_ACTIVE_MODE_THRESHOLD
diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp
index df51c77..c595bf9 100644
--- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp
+++ b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp
@@ -39,22 +39,6 @@
 CHIP_ERROR FactoryDataProviderImpl::Init()
 {
     CHIP_ERROR error = CHIP_NO_ERROR;
-    uint32_t sum     = 0;
-
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-    ReturnErrorOnFailure(SetCustomIds());
-#endif
-
-    for (uint8_t i = 1; i < FactoryDataProvider::kNumberOfIds; i++)
-    {
-        sum += maxLengths[i];
-    }
-
-    if (sum > kFactoryDataSize)
-    {
-        ChipLogError(DeviceLayer, "Max size of factory data: %lu is bigger than reserved factory data size: %lu", sum,
-                     kFactoryDataSize);
-    }
 
 #if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
     error = ValidateWithRestore();
diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h
index f8d5157..b359a6d 100644
--- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h
+++ b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h
@@ -24,7 +24,6 @@
 
 /**
  * This class provides K32W0 specific factory data features.
- * CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER       - application defined factory data provider
  * CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR - enables factory data OTA
  */
 
@@ -36,13 +35,6 @@
     CHIP_ERROR Init() override;
     CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
 
-#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
-    virtual ~FactoryDataProviderImpl() {}
-    // Custom factory data providers must implement this method in order to define
-    // their own custom IDs.
-    virtual CHIP_ERROR SetCustomIds() = 0;
-#endif
-
 #if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
     using RestoreMechanism = CHIP_ERROR (*)(void);
 
diff --git a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp
index 5d98fc1..b01854c 100644
--- a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp
+++ b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp
@@ -34,9 +34,6 @@
 #include "app_dual_mode_low_power.h"
 #include "app_dual_mode_switch.h"
 #include "k32w0-chip-mbedtls-config.h"
-#include <AppTask.h> // nogncheck
-
-#include "app_config.h"
 
 using namespace ::chip;
 using namespace ::chip::Inet;
@@ -107,22 +104,6 @@
     return dualModeStates.threadWarmBootInitTime;
 }
 
-extern "C" bleResult_t App_PostCallbackMessage(appCallbackHandler_t handler, appCallbackParam_t param)
-{
-    AppEvent event;
-    event.Type    = AppEvent::kEventType_Lp;
-    event.Handler = handler;
-    event.param   = param;
-
-#if ENABLE_LOW_POWER_LOGS
-    K32W_LOG("App_PostCallbackMessage %d", (uint32_t) param);
-#endif
-
-    GetAppTask().PostEvent(&event);
-
-    return gBleSuccess_c;
-}
-
 WEAK void dm_switch_wakeupCallBack(void)
 {
     BOARD_SetClockForWakeup();
diff --git a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp b/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp
index 438623d..d40d2ae 100644
--- a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp
+++ b/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp
@@ -73,7 +73,8 @@
 
 CHIP_ERROR OTAFactoryDataProcessor::ApplyAction()
 {
-    CHIP_ERROR error = CHIP_NO_ERROR;
+    CHIP_ERROR error           = CHIP_NO_ERROR;
+    FactoryProvider * provider = nullptr;
 
     ReturnErrorOnFailure(Read());
     ReturnErrorOnFailure(Backup());
@@ -83,7 +84,16 @@
     SuccessOrExit(error = Update((uint8_t) Tags::kPaiCertificateId, mPayload.mCertPai));
     SuccessOrExit(error = Update((uint8_t) Tags::kCertDeclarationId, mPayload.mCertDeclaration));
 
-    error = FactoryProviderImpl::UpdateData(mFactoryData);
+    SuccessOrExit(error = FactoryProviderImpl::UpdateData(mFactoryData));
+
+    /* Check integrity of freshly copied data. If validation fails, OTA will be aborted
+     * and factory data will be restored to the previous version. Use device instance info
+     * provider getter to access the factory data provider instance. The instance is created
+     * by the application, so it's easier to access it this way.*/
+    provider = static_cast<FactoryProvider *>(DeviceLayer::GetDeviceInstanceInfoProvider());
+    SuccessOrExit(error = ((provider != nullptr) ? CHIP_NO_ERROR : CHIP_ERROR_INVALID_ADDRESS));
+
+    error = provider->Validate();
 
 exit:
     if (error != CHIP_NO_ERROR)
diff --git a/src/platform/nxp/k32w/k32w1/BUILD.gn b/src/platform/nxp/k32w/k32w1/BUILD.gn
index 187a736..8ad1192 100644
--- a/src/platform/nxp/k32w/k32w1/BUILD.gn
+++ b/src/platform/nxp/k32w/k32w1/BUILD.gn
@@ -58,6 +58,8 @@
     "ram_storage.h",
   ]
 
+  public = [ "${chip_root}/src/platform/nxp/k32w/k32w1/BLEManagerImpl.h" ]
+
   public_deps = [ "${chip_root}/src/platform:platform_base" ]
 
   if (chip_with_low_power != 0) {
@@ -65,6 +67,8 @@
   }
 
   if (chip_enable_ota_requestor) {
+    public += [ "../common/OTAImageProcessorImpl.h" ]
+
     sources += [
       "../common/OTAImageProcessorImpl.cpp",
       "../common/OTAImageProcessorImpl.h",