[NXP][k32w1] Remove the need for extra DAC private key conversion binary (#32699)

* [NXP][k32w1] Add SSS DAC private key conversion at init / Use plain-text DAC key

 * Do SSS DAC private key conversion at initialization if needed.
 * Do not use extra SSS conversion binary anymore.
 * Add option to use DAC private key in plain text.

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

* [NXP][k32w1] Update manufacturing flow to not use chip_convert_dac_private_key

 * Using chip_convert_dac_private_key option is not needed anymore.
 * Use chip_use_plain_dac_key=true for plain-text DAC private key.

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

* [NXP][k32w1] Remove example_convert_dac_private_key.jlink

 * Using chip_convert_dac_private_key option is not needed anymore,
 making the jlink script obsolete.

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

* Restyled by prettier-markdown

* Restyled by prettier-markdown

* Check SSS_ExportBlob return status

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

---------

Signed-off-by: Andrei Menzopol <andrei.menzopol@nxp.com>
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/docs/guides/nxp_manufacturing_flow.md b/docs/guides/nxp_manufacturing_flow.md
index 6cc3005..bad70db 100644
--- a/docs/guides/nxp_manufacturing_flow.md
+++ b/docs/guides/nxp_manufacturing_flow.md
@@ -215,26 +215,15 @@
 factory data and will be imported in the `SSS` at initialization, by the factory
 data provider instance.
 
-The conversion process shall happen at manufacturing time and should be run one
-time only:
+The application will check at initialization whether the DAC private key has
+been converted or not and convert it if needed. However, the conversion process
+should be done at manufacturing time for security reasons.
+
+There is no need for an extra binary.
 
 -   Write factory data binary.
--   Build the application with
-    `chip_with_factory_data=1 chip_convert_dac_private_key=1` set.
--   Write the application to the board and let it run.
-
-After the conversion process:
-
--   Make sure the application is built with `chip_with_factory_data=1`, but
-    without `chip_convert_dac_private_key` arg, since conversion already
-    happened.
--   Write the application to the board.
-
-If you are using Jlink, you can see a conversion script example in:
-
-```shell
-./scripts/tools/nxp/factory_data_generator/k32w1/example_convert_dac_private_key.jlink
-```
+-   Build the application with `chip_with_factory_data=1` set.
+-   Write the application to the board and use it as usual.
 
 Factory data should now contain a corresponding encrypted blob instead of the
 DAC private key.
@@ -251,6 +240,9 @@
 Please note that `--dac_key` now points to a binary file that contains the
 encrypted blob.
 
+The user can use the DAC private in plain text instead of using the `SSS` by
+adding the following gn argument `chip_use_plain_dac_key=true`.
+
 ### 6.2 RW61X
 
 Supported platforms:
diff --git a/scripts/tools/nxp/factory_data_generator/k32w1/example_convert_dac_private_key.jlink b/scripts/tools/nxp/factory_data_generator/k32w1/example_convert_dac_private_key.jlink
deleted file mode 100644
index d31c137..0000000
--- a/scripts/tools/nxp/factory_data_generator/k32w1/example_convert_dac_private_key.jlink
+++ /dev/null
@@ -1,16 +0,0 @@
-reset
-halt
-// Factory data size is one internal flash sector (8K).
-// Factory data address is retrieved from the map file.
-erase 0xec000 0xee000 noreset
-// Load factory data and conversion application, then
-// wait for 10 seconds and load the "real" application.
-loadfile factory_data.bin 0xec000
-loadfile chip-k32w1-light-example-before-conversion.srec
-reset
-go
-Sleep 10000
-loadfile chip-k32w1-light-example-after-conversion.srec
-reset
-go
-quit
\ No newline at end of file
diff --git a/src/platform/nxp/k32w/k32w1/BUILD.gn b/src/platform/nxp/k32w/k32w1/BUILD.gn
index 53a4b4d..3035220 100644
--- a/src/platform/nxp/k32w/k32w1/BUILD.gn
+++ b/src/platform/nxp/k32w/k32w1/BUILD.gn
@@ -61,6 +61,12 @@
     "ram_storage.h",
   ]
 
+  if (chip_use_plain_dac_key) {
+    defines += [ "CHIP_USE_PLAIN_DAC_KEY=1" ]
+  } else {
+    defines += [ "CHIP_USE_PLAIN_DAC_KEY=0" ]
+  }
+
   public = [
     "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h",
     "${chip_root}/src/credentials/examples/DeviceAttestationCredsExample.h",
@@ -107,10 +113,6 @@
         "${chip_root}/src/credentials/CHIPCert.h",
         "${chip_root}/src/credentials/CertificationDeclaration.h",
       ]
-
-      if (chip_convert_dac_private_key == 1) {
-        defines += [ "CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY=1" ]
-      }
     }
 
     public_deps += [ "${mbedtls_root}:mbedtls" ]
diff --git a/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.cpp b/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.cpp
index c3c9138..764e3f6 100644
--- a/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.cpp
+++ b/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.cpp
@@ -15,29 +15,30 @@
  *    limitations under the License.
  */
 
-#include <platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h>
-
-#if CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
 #include "fsl_adapter_flash.h"
-#endif
+#include <platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h>
 
 namespace chip {
 namespace DeviceLayer {
 
+#if !CHIP_USE_PLAIN_DAC_KEY
 // SSS adds 24 bytes of metadata when creating the blob
 static constexpr size_t kSssBlobMetadataLength = 24;
 static constexpr size_t kPrivateKeyBlobLength  = Crypto::kP256_PrivateKey_Length + kSssBlobMetadataLength;
+#endif
 
 FactoryDataProviderImpl::~FactoryDataProviderImpl()
 {
+#if !CHIP_USE_PLAIN_DAC_KEY
     SSS_KEY_OBJ_FREE(&mContext);
+#endif
 }
 
 CHIP_ERROR FactoryDataProviderImpl::Init()
 {
     CHIP_ERROR error = CHIP_NO_ERROR;
 
-#if CHIP_DEVICE_CONFIG_ENABLE_SSS_API_TEST
+#if CHIP_DEVICE_CONFIG_ENABLE_SSS_API_TEST && !CHIP_USE_PLAIN_DAC_KEY
     SSS_RunApiTest();
 #endif
 
@@ -47,16 +48,56 @@
         ChipLogError(DeviceLayer, "Factory data init failed with: %s", ErrorStr(error));
     }
 
+#if !CHIP_USE_PLAIN_DAC_KEY
     ReturnErrorOnFailure(SSS_InitContext());
-#if CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
     ReturnErrorOnFailure(SSS_ConvertDacKey());
-    ReturnErrorOnFailure(Validate());
-#endif
     ReturnErrorOnFailure(SSS_ImportPrivateKeyBlob());
+#endif
 
     return error;
 }
 
+#if CHIP_USE_PLAIN_DAC_KEY
+CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    Crypto::P256ECDSASignature signature;
+    Crypto::P256Keypair keypair;
+    Crypto::P256SerializedKeypair serializedKeypair;
+    uint8_t keyBuf[Crypto::kP256_PrivateKey_Length];
+    MutableByteSpan dacPrivateKeySpan(keyBuf);
+    uint16_t keySize = 0;
+
+    VerifyOrExit(!outSignBuffer.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(!messageToSign.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(outSignBuffer.size() >= signature.Capacity(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    /* Get private key of DAC certificate from reserved section */
+    error = SearchForId(FactoryDataId::kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize);
+    SuccessOrExit(error);
+    dacPrivateKeySpan.reduce_size(keySize);
+    VerifyOrExit(keySize == Crypto::kP256_PrivateKey_Length, error = CHIP_ERROR_WRONG_KEY_TYPE);
+
+    /* Only the private key is used when signing */
+    error = serializedKeypair.SetLength(Crypto::kP256_PublicKey_Length + dacPrivateKeySpan.size());
+    SuccessOrExit(error);
+    memcpy(serializedKeypair.Bytes() + Crypto::kP256_PublicKey_Length, dacPrivateKeySpan.data(), dacPrivateKeySpan.size());
+
+    error = keypair.Deserialize(serializedKeypair);
+    SuccessOrExit(error);
+
+    error = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature);
+    SuccessOrExit(error);
+
+    error = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
+
+exit:
+    /* Sanitize temporary buffer */
+    memset(keyBuf, 0, Crypto::kP256_PrivateKey_Length);
+    return error;
+}
+
+#else
 CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
 {
     Crypto::P256ECDSASignature signature;
@@ -118,7 +159,6 @@
     return error;
 }
 
-#if CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
 CHIP_ERROR FactoryDataProviderImpl::SSS_ConvertDacKey()
 {
     size_t blobSize                     = kPrivateKeyBlobLength;
@@ -126,10 +166,18 @@
     uint8_t blob[kPrivateKeyBlobLength] = { 0 };
     uint8_t * data                      = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(newSize));
     uint32_t offset                     = 0;
+    bool convNeeded                     = true;
 
     VerifyOrReturnError(data != nullptr, CHIP_ERROR_INTERNAL);
 
-    ReturnErrorOnFailure(SSS_ExportBlob(blob, &blobSize, offset));
+    ReturnErrorOnFailure(SSS_ExportBlob(blob, &blobSize, offset, convNeeded));
+    if (!convNeeded)
+    {
+        ChipLogError(DeviceLayer, "SSS: DAC private key already converted to blob");
+        chip::Platform::MemoryFree(data);
+        return CHIP_NO_ERROR;
+    }
+
     ChipLogError(DeviceLayer, "SSS: extracted blob from DAC private key");
 
     hal_flash_status_t status = HAL_FlashRead(kFactoryDataStart, newSize - kSssBlobMetadataLength, data);
@@ -149,22 +197,31 @@
     chip::Platform::MemoryFree(data);
     ChipLogError(DeviceLayer, "SSS: sanitized RAM cache");
 
+    ReturnErrorOnFailure(Validate());
+
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR FactoryDataProviderImpl::SSS_ExportBlob(uint8_t * data, size_t * dataLen, uint32_t & offset)
+CHIP_ERROR FactoryDataProviderImpl::SSS_ExportBlob(uint8_t * data, size_t * dataLen, uint32_t & offset, bool & isNeeded)
 {
     CHIP_ERROR error = CHIP_NO_ERROR;
     auto res         = kStatus_SSS_Success;
 
-    uint8_t keyBuf[Crypto::kP256_PrivateKey_Length];
+    uint8_t keyBuf[kPrivateKeyBlobLength];
     MutableByteSpan dacPrivateKeySpan(keyBuf);
     uint16_t keySize = 0;
+    isNeeded         = true;
 
     error = SearchForId(FactoryDataId::kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize, &offset);
     SuccessOrExit(error);
     dacPrivateKeySpan.reduce_size(keySize);
 
+    if (keySize == kPrivateKeyBlobLength)
+    {
+        isNeeded = false;
+        return CHIP_NO_ERROR;
+    }
+
     res = SSS_KEY_STORE_SET_KEY(&mContext, dacPrivateKeySpan.data(), Crypto::kP256_PrivateKey_Length, keySize * 8,
                                 kSSS_KeyPart_Private);
     VerifyOrExit(res == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL);
@@ -197,7 +254,6 @@
 
     return CHIP_NO_ERROR;
 }
-#endif // CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
 
 #if CHIP_DEVICE_CONFIG_ENABLE_SSS_API_TEST
 
@@ -298,6 +354,7 @@
     SSS_KEY_OBJ_FREE(&mContext);
 }
 #endif // CHIP_DEVICE_CONFIG_ENABLE_SSS_API_TEST
+#endif // CHIP_USE_PLAIN_DAC_KEY
 
 } // namespace DeviceLayer
 } // namespace chip
diff --git a/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h b/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h
index 67bef19..f81b5d1 100644
--- a/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h
+++ b/src/platform/nxp/k32w/k32w1/FactoryDataProviderImpl.h
@@ -19,21 +19,8 @@
 #include <crypto/CHIPCryptoPAL.h>
 #include <platform/nxp/k32w/common/FactoryDataProvider.h>
 
+#if !CHIP_USE_PLAIN_DAC_KEY
 #include "sss_crypto.h"
-
-/* This flag should be defined when the factory data contains
- * the DAC private key in plain text. It usually occurs in
- * manufacturing.
- *
- * The init phase will use S200 to export an encrypted blob,
- * then overwrite the private key section from internal flash.
- *
- * Should be used one time only for securing the private key.
- * The manufacturer will then flash the real image, which shall
- * not define this flag.
- */
-#ifndef CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
-#define CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY 0
 #endif
 
 /* This flag should be defined to run SSS_RunApiTest tests.
@@ -59,12 +46,13 @@
     CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
 
 private:
+#if !CHIP_USE_PLAIN_DAC_KEY
+
     CHIP_ERROR SSS_InitContext();
     CHIP_ERROR SSS_ImportPrivateKeyBlob();
     CHIP_ERROR SSS_Sign(uint8_t * digest, Crypto::P256ECDSASignature & signature);
-#if CHIP_DEVICE_CONFIG_SECURE_DAC_PRIVATE_KEY
     /*!
-     * \brief Convert DAC private key to an SSS encrypted blob and update factory data
+     * \brief Convert DAC private key to an SSS encrypted blob and update factory data if not already done
      *
      * @note This API should be called in manufacturing process context to replace
      *       DAC private key with an SSS encrypted blob. The conversion will be a
@@ -74,15 +62,16 @@
     CHIP_ERROR SSS_ConvertDacKey();
 
     /*!
-     * \brief Export an SSS encrypted blob from the DAC private key found in factory data
+     * \brief Check and export an SSS encrypted blob from the DAC private key found in factory data if needed
      *
      * @param data        Pointer to an allocated buffer
      * @param dataLen     Pointer to a variable that will store the blob length
      * @param offset      Offset of private key from the start of factory data payload address (after header)
+     * @param isNeeded    Will be set to true if conversion is needed
      *
      * @retval #CHIP_NO_ERROR if conversion to blob was successful.
      */
-    CHIP_ERROR SSS_ExportBlob(uint8_t * data, size_t * dataLen, uint32_t & offset);
+    CHIP_ERROR SSS_ExportBlob(uint8_t * data, size_t * dataLen, uint32_t & offset, bool & isNeeded);
 
     /*!
      * \brief Replace DAC private key with the specified SSS encrypted blob
@@ -97,12 +86,13 @@
      * @retval #CHIP_NO_ERROR if conversion to blob was successful.
      */
     CHIP_ERROR ReplaceWithBlob(uint8_t * data, uint8_t * blob, size_t blobLen, uint32_t offset);
-#endif
+
 #if CHIP_DEVICE_CONFIG_ENABLE_SSS_API_TEST
     void SSS_RunApiTest();
 #endif
 
     sss_sscp_object_t mContext;
+#endif // CHIP_USE_PLAIN_DAC_KEY
 };
 
 } // namespace DeviceLayer
diff --git a/src/platform/nxp/k32w/k32w1/args.gni b/src/platform/nxp/k32w/k32w1/args.gni
index 2de3577..8b90982 100644
--- a/src/platform/nxp/k32w/k32w1/args.gni
+++ b/src/platform/nxp/k32w/k32w1/args.gni
@@ -19,8 +19,8 @@
 declare_args() {
   chip_with_ot_cli = 0
   chip_with_low_power = 0
-  chip_convert_dac_private_key = 0
   sdk_release = 1
+  chip_use_plain_dac_key = false
 }
 
 nxp_platform = "k32w/k32w1"