You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/04/21 03:20:18 UTC

(nuttx-apps) branch master updated: controlse: add accesslib for the se05x secure element

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new cecc2e762 controlse: add accesslib for the se05x secure element
cecc2e762 is described below

commit cecc2e762b54c070fc80d3bb598e729cbd134e82
Author: Andre Heinemans <an...@nxp.com>
AuthorDate: Fri Apr 19 12:29:05 2024 +0200

    controlse: add accesslib for the se05x secure element
---
 crypto/controlse/CMakeLists.txt                    |  45 ++
 crypto/controlse/Kconfig                           |   5 +-
 crypto/controlse/Makefile                          |   7 +-
 crypto/controlse/ccertificate.cxx                  | 532 +++++++++++++++
 crypto/controlse/ccsr.cxx                          | 212 ++++++
 crypto/controlse/chex_util.cxx                     | 100 +++
 crypto/controlse/cmbedtls_se05x_extension.hxx      | 188 ++++++
 crypto/controlse/controlse_main.c                  | 737 ---------------------
 crypto/controlse/controlse_main.cxx                | 711 ++++++++++++++++++++
 crypto/controlse/cpublic_key.cxx                   | 243 +++++++
 crypto/controlse/csan_builder.cxx                  | 124 ++++
 crypto/controlse/csecure_element.cxx               | 189 ++++++
 crypto/controlse/cserial_number.cxx                |  94 +++
 crypto/controlse/cstring.cxx                       | 141 ++++
 crypto/controlse/mbedtls_extension.c               | 310 ---------
 crypto/controlse/mbedtls_extension.h               |  40 --
 crypto/controlse/x509_utils.c                      | 350 ----------
 crypto/controlse/x509_utils.h                      |  54 --
 include/crypto/controlse/ccertificate.hxx          | 122 ++++
 include/crypto/controlse/ccsr.hxx                  |  92 +++
 include/crypto/controlse/chex_util.hxx             |  62 ++
 include/crypto/controlse/cpublic_key.hxx           |  82 +++
 include/crypto/controlse/csan_builder.hxx          |  69 ++
 include/crypto/controlse/csecure_element.hxx       |  73 ++
 include/crypto/controlse/cserial_number.hxx        |  62 ++
 include/crypto/controlse/cstring.hxx               |  64 ++
 include/crypto/controlse/isecure_element.hxx       |  71 ++
 .../crypto/controlse/isecure_element_object.hxx    |  51 ++
 28 files changed, 3335 insertions(+), 1495 deletions(-)

diff --git a/crypto/controlse/CMakeLists.txt b/crypto/controlse/CMakeLists.txt
new file mode 100644
index 000000000..72fb36e01
--- /dev/null
+++ b/crypto/controlse/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ##############################################################################
+# apps/crypto/controlse/CMakeLists.txt
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you 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.
+#
+# ##############################################################################
+
+if(CONFIG_CRYPTO_CONTROLSE)
+
+  set(MBEDTLS_DIR ${CMAKE_BINARY_DIR}/apps/include/mbedtls)
+
+  nuttx_add_application(
+    NAME
+    ${CONFIG_CRYPTO_CONTROLSE_PROGNAME}
+    STACKSIZE
+    ${CONFIG_CRYPTO_CONTROLSE_STACKSIZE}
+    MODULE
+    ${CONFIG_CRYPTO_CONTROLSE}
+    SRCS
+    controlse_main.cxx
+    chex_util.cxx
+    csecure_element.cxx
+    cstring.cxx
+    ccertificate.cxx
+    ccsr.cxx
+    cpublic_key.cxx
+    cserial_number.cxx
+    csan_builder.cxx
+    INCLUDE_DIRECTORIES
+    ${MBEDTLS_DIR})
+
+endif()
diff --git a/crypto/controlse/Kconfig b/crypto/controlse/Kconfig
index 550d09260..e1da37dcd 100644
--- a/crypto/controlse/Kconfig
+++ b/crypto/controlse/Kconfig
@@ -18,8 +18,9 @@ config CRYPTO_CONTROLSE
 	select MBEDTLS_X509_CSR_WRITE_C
 	select MBEDTLS_X509_CRT_WRITE_C
 	---help---
-		Enable the controlse utility. This program is used control the
-		secure element device
+		Enable the controlse library and utility. It provides an
+		access library to the secure element device. The utility can
+		control the secure element device from the nuttx shell
 
 if CRYPTO_CONTROLSE
 
diff --git a/crypto/controlse/Makefile b/crypto/controlse/Makefile
index 6ad484059..c338507d1 100644
--- a/crypto/controlse/Makefile
+++ b/crypto/controlse/Makefile
@@ -18,6 +18,8 @@
 #
 ############################################################################
 
+# Copyright 2023, 2024 NXP
+
 include $(APPDIR)/Make.defs
 
 # controlse built-in application info
@@ -28,7 +30,8 @@ STACKSIZE = $(CONFIG_CRYPTO_CONTROLSE_STACKSIZE)
 
 # controlse main source
 
-MAINSRC = controlse_main.c
-CSRCS = x509_utils.c mbedtls_extension.c
+MAINSRC = controlse_main.cxx
+CXXSRCS = chex_util.cxx	csecure_element.cxx cstring.cxx ccertificate.cxx\
+	ccsr.cxx cpublic_key.cxx cserial_number.cxx csan_builder.cxx
 
 include $(APPDIR)/Application.mk
diff --git a/crypto/controlse/ccertificate.cxx b/crypto/controlse/ccertificate.cxx
new file mode 100644
index 000000000..5731c4ddd
--- /dev/null
+++ b/crypto/controlse/ccertificate.cxx
@@ -0,0 +1,532 @@
+//***************************************************************************
+// apps/crypto/controlse/ccertificate.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//***************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include "crypto/controlse/ccertificate.hxx"
+
+#include "cmbedtls_se05x_extension.hxx"
+#include "crypto/controlse/chex_util.hxx"
+#include "crypto/controlse/cpublic_key.hxx"
+#include "crypto/controlse/cserial_number.hxx"
+#include "crypto/controlse/isecure_element.hxx"
+#include <mbedtls/oid.h>
+#include <mbedtls/pem.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/x509_csr.h>
+#include <string.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Private Data
+//***************************************************************************
+
+static constexpr int SECONDS_IN_DAY = (60 * 60 * 24);
+static constexpr size_t TBS_HASH_BUFFER_SIZE = 32;
+
+static constexpr char certificate_header[] = "-----BEGIN CERTIFICATE-----\n";
+static constexpr char certificate_footer[] = "-----END CERTIFICATE-----\n";
+static constexpr size_t datetime_size = 15;
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CCertificate::CCertificate(const ISecureElement &se, uint32_t keystore_id)
+{
+  mbedtls_x509_crt_init(&crt);
+  is_loaded = LoadFromSecureElement(se, keystore_id);
+}
+
+CCertificate::CCertificate(const uint8_t *crt_der_or_pem, size_t crt_size)
+{
+  mbedtls_x509_crt_init(&crt);
+  is_loaded = LoadFromDerOrPem(crt_der_or_pem, crt_size);
+}
+
+static void GetCurrentDateTime(char datetime[datetime_size], int seconds)
+{
+  time_t rawtime;
+  struct tm tm_info;
+  time(&rawtime);
+  rawtime += seconds;
+  strftime(datetime, datetime_size, "%Y%m%d%H%M%S",
+           gmtime_r(&rawtime, &tm_info));
+}
+
+CCertificate::CCertificate(const ISecureElement &se,
+                           const uint8_t *csr_der_or_pem, size_t csr_size,
+                           uint32_t keystore_id)
+{
+  mbedtls_x509_crt_init(&crt);
+  char from_datetime[datetime_size];
+  char to_datetime[datetime_size];
+  GetCurrentDateTime(from_datetime, 0);
+  GetCurrentDateTime(to_datetime, SECONDS_IN_DAY);
+  is_loaded = LoadFromCsrDerOrPem(se, csr_der_or_pem, csr_size, keystore_id,
+                                  from_datetime, to_datetime);
+}
+
+CCertificate::CCertificate(const ISecureElement &se,
+                           const uint8_t *csr_der_or_pem, size_t csr_size,
+                           uint32_t keystore_id, const char *from_datetime,
+                           const char *to_datetime)
+{
+  mbedtls_x509_crt_init(&crt);
+  is_loaded = LoadFromCsrDerOrPem(se, csr_der_or_pem, csr_size, keystore_id,
+                                  from_datetime, to_datetime);
+}
+
+CCertificate::~CCertificate() { mbedtls_x509_crt_free(&crt); }
+
+bool CCertificate::IsLoaded() const { return is_loaded; }
+
+bool CCertificate::StoreOnSecureElement(const ISecureElement &se,
+                                        uint32_t keystore_id) const
+{
+  struct se05x_key_transmission_s args;
+  args.entry.id = keystore_id;
+  args.content.buffer = crt.raw.p;
+  args.content.buffer_size = crt.raw.len;
+  args.content.buffer_content_size = crt.raw.len;
+  return se.SetData(args);
+}
+
+bool CCertificate::LoadFromSecureElement(const ISecureElement &se,
+                                         uint32_t keystore_id)
+{
+  size_t certificate_der_size = 1000;
+  uint8_t *certificate_der = new uint8_t[certificate_der_size];
+  struct se05x_key_transmission_s args
+      = { .entry = { .id = keystore_id },
+          .content = { .buffer = certificate_der,
+                       .buffer_size = certificate_der_size } };
+  bool result = se.GetData(args);
+
+  if (result)
+    {
+      result = 0
+               == mbedtls_x509_crt_parse(&crt, certificate_der,
+                                         args.content.buffer_content_size);
+    }
+
+  delete[] certificate_der;
+  return result;
+}
+
+bool CCertificate::LoadFromDerOrPem(const uint8_t *crt_der_or_pem,
+                                    size_t crt_size)
+{
+  return 0 == mbedtls_x509_crt_parse(&crt, crt_der_or_pem, crt_size);
+}
+
+bool CCertificate::LoadFromCsrDerOrPem(const ISecureElement &se,
+                                       const uint8_t *csr_der_or_pem,
+                                       size_t csr_size, uint32_t keystore_id,
+                                       const char *from_datetime,
+                                       const char *to_datetime)
+{
+  mbedtls_x509_csr csr;
+  mbedtls_x509_csr_init(&csr);
+  auto result = 0 == mbedtls_x509_csr_parse(&csr, csr_der_or_pem, csr_size);
+
+  mbedtls_x509write_cert crt_builder;
+  mbedtls_x509write_crt_init(&crt_builder);
+  char subject_name[200];
+  if (result)
+    {
+      mbedtls_x509write_crt_set_version(&crt_builder,
+                                        MBEDTLS_X509_CRT_VERSION_3);
+      result = 0 < mbedtls_x509_dn_gets(subject_name, sizeof(subject_name),
+                                        &csr.subject);
+    }
+
+  mbedtls_pk_context key;
+  mbedtls_pk_init(&key);
+  if (result)
+    {
+      result = 0
+               == MbedtlsSe05xExtension::mbedtls_pk_setup_key_se05x(
+                   key, se, keystore_id);
+    }
+
+  mbedtls_pk_context public_key;
+  public_key.pk_ctx = csr.pk.pk_ctx;
+  public_key.pk_info = csr.pk.pk_info;
+
+  // Invalidate the public key in CSR
+  // The public key is transferred to CRT so the CSR may not free the memory
+  csr.pk.pk_ctx = nullptr;
+  csr.pk.pk_info = nullptr;
+  mbedtls_x509_csr_free(&csr);
+
+  if (result)
+    {
+      mbedtls_x509write_crt_set_subject_key(&crt_builder, &public_key);
+      mbedtls_x509write_crt_set_issuer_key(&crt_builder, &key);
+      result = 0
+               == mbedtls_x509write_crt_set_subject_name(&crt_builder,
+                                                         subject_name);
+    }
+
+  if (result)
+    {
+      result = 0
+               == mbedtls_x509write_crt_set_issuer_name(&crt_builder,
+                                                  "CN=CA,O=controlse,C=NL");
+    }
+
+  mbedtls_mpi serial;
+  mbedtls_mpi_init(&serial);
+  if (result)
+    {
+      mbedtls_x509write_crt_set_md_alg(&crt_builder, MBEDTLS_MD_SHA256);
+      result = 0 == mbedtls_mpi_read_string(&serial, 10, "1");
+    }
+
+  if (result)
+    {
+      result = 0 == mbedtls_x509write_crt_set_serial(&crt_builder, &serial);
+    }
+
+  if (result)
+    {
+      result = 0
+               == mbedtls_x509write_crt_set_validity(
+                   &crt_builder, from_datetime, to_datetime);
+    }
+
+  size_t buf_size = 1000;
+  uint8_t *buf = nullptr;
+  if (result)
+    {
+      buf = new uint8_t[buf_size];
+      result = buf != nullptr;
+    }
+
+  size_t buf_content_size;
+  if (result)
+    {
+      auto der_result
+          = mbedtls_x509write_crt_der(&crt_builder, buf, buf_size, nullptr, 0);
+      buf_content_size = der_result;
+      result = 0 < der_result;
+    }
+
+  mbedtls_x509write_crt_free(&crt_builder);
+  MbedtlsSe05xExtension::mbedtls_pk_free_se05x(key);
+  mbedtls_pk_free(&key);
+  mbedtls_pk_free(&public_key);
+  mbedtls_mpi_free(&serial);
+
+  if (result)
+    {
+      result = LoadFromDerOrPem(buf + buf_size - buf_content_size,
+                                buf_content_size);
+    }
+
+  if (buf)
+    {
+      delete[] buf;
+    }
+  return result;
+}
+
+bool CCertificate::VerifyAgainst(const ISecureElement &se,
+                                 uint32_t verify_against_id) const
+{
+  if (!is_loaded)
+    {
+      return false;
+    }
+
+  uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
+  bool result = 0 == mbedtls_sha256(crt.tbs.p, crt.tbs.len, tbs_buffer, 0);
+
+  if (result)
+    {
+      struct se05x_signature_s verify_args = {
+        .key_id = verify_against_id,
+        .algorithm = SE05X_ALGORITHM_SHA256,
+        .tbs = { .buffer = tbs_buffer,
+                 .buffer_size = sizeof(tbs_buffer),
+                 .buffer_content_size = sizeof(tbs_buffer) },
+        .signature = { .buffer = crt.sig.p,
+                       .buffer_size = crt.sig.len,
+                       .buffer_content_size = crt.sig.len },
+      };
+      result = se.Verify(verify_args);
+    }
+
+  return result;
+}
+
+static bool check_time(const mbedtls_x509_time *before,
+                       const mbedtls_x509_time *after)
+{
+  if (before->year > after->year)
+    return false;
+
+  if (before->year == after->year && before->mon > after->mon)
+    return false;
+
+  if (before->year == after->year && before->mon == after->mon
+      && before->day > after->day)
+    return false;
+
+  if (before->year == after->year && before->mon == after->mon
+      && before->day == after->day && before->hour > after->hour)
+    return false;
+
+  if (before->year == after->year && before->mon == after->mon
+      && before->day == after->day && before->hour == after->hour
+      && before->min > after->min)
+    return false;
+
+  if (before->year == after->year && before->mon == after->mon
+      && before->day == after->day && before->hour == after->hour
+      && before->min == after->min && before->sec > after->sec)
+    return false;
+
+  return true;
+}
+
+int CCertificate::TestValidTimerange(time_t now) const
+{
+
+  auto lt = gmtime(&now);
+
+  mbedtls_x509_time mbedtls_now;
+  mbedtls_now.year = lt->tm_year + 1900;
+  mbedtls_now.mon = lt->tm_mon + 1;
+  mbedtls_now.day = lt->tm_mday;
+  mbedtls_now.hour = lt->tm_hour;
+  mbedtls_now.min = lt->tm_min;
+  mbedtls_now.sec = lt->tm_sec;
+
+  if (!check_time(&mbedtls_now, &crt.valid_to))
+    {
+      return -1;
+    }
+  if (!check_time(&crt.valid_from, &mbedtls_now))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+
+CPublicKey *CCertificate::GetPublicKey() const
+{
+  if (!is_loaded)
+    {
+      return nullptr;
+    }
+
+  size_t root_key_buf_size = 100;
+  uint8_t *root_key_buf = new uint8_t[root_key_buf_size];
+
+  bool result = false;
+  if (root_key_buf)
+    {
+      mbedtls_ecp_keypair *keypair
+          = reinterpret_cast<mbedtls_ecp_keypair *>(crt.pk.pk_ctx);
+      result = 0
+               == mbedtls_ecp_point_write_binary(
+                   &keypair->grp, &keypair->Q, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                   &root_key_buf_size, root_key_buf, root_key_buf_size);
+    }
+
+  CPublicKey *public_key
+      = result ? new CPublicKey(root_key_buf, root_key_buf_size) : nullptr;
+
+  if (root_key_buf)
+    {
+      delete[] root_key_buf;
+    }
+
+  return public_key;
+}
+
+char *CCertificate::GetOid(const char *oid) const
+{
+  if (!is_loaded)
+    {
+      return nullptr;
+    }
+  auto item = mbedtls_asn1_find_named_data(&crt.subject, oid, 3);
+
+  if (item)
+    {
+      auto data = new char[item->val.len + 1];
+      memcpy(data, item->val.p, item->val.len);
+      data[item->val.len] = 0;
+      return data;
+    }
+  return nullptr;
+}
+
+CSerialNumber *CCertificate::GetSerialNumber() const
+{
+  if (!is_loaded)
+    {
+      return nullptr;
+    }
+
+  if (crt.serial.len == CSerialNumber::SERIAL_NUMBER_SIZE)
+    {
+      auto serial = new CSerialNumber(crt.serial.p);
+      return serial;
+    }
+  return nullptr;
+}
+
+size_t CCertificate::GetNumberOfSubjectAlternativeNames() const
+{
+  if (!is_loaded)
+    {
+      return 0;
+    }
+  size_t size = 0;
+  auto current = &crt.subject_alt_names;
+
+  do
+    {
+      if (current->buf.tag
+          == (MBEDTLS_ASN1_CONTEXT_SPECIFIC
+              | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER))
+        {
+          size++;
+        }
+      current = current->next;
+    }
+  while (current);
+  return size;
+}
+
+char *CCertificate::GetSubjectAlternativeName(int item) const
+{
+  if (!is_loaded)
+    {
+      return nullptr;
+    }
+
+  auto current = &crt.subject_alt_names;
+
+  // go to first uri
+  while (current->buf.tag
+         != (MBEDTLS_ASN1_CONTEXT_SPECIFIC
+             | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER))
+    {
+      current = current->next;
+      if (current == nullptr)
+        {
+          return nullptr;
+        }
+    }
+
+  // go the next uri until we get to the correct item
+  for (int i = 0; i < item; i++)
+    {
+      do
+        {
+          current = current->next;
+          if (current == nullptr)
+            {
+              return nullptr;
+            }
+        }
+      while (current->buf.tag
+             != (MBEDTLS_ASN1_CONTEXT_SPECIFIC
+                 | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER));
+    }
+
+  auto san = new char[current->buf.len + 1];
+  if (san)
+    {
+      memcpy(san, current->buf.p, current->buf.len);
+      san[current->buf.len] = 0;
+    }
+  return san;
+}
+
+size_t CCertificate::GetDer(uint8_t **der) const
+{
+  if (!is_loaded)
+    {
+      return 0;
+    }
+  *der = new uint8_t[crt.raw.len];
+  memcpy(*der, crt.raw.p, crt.raw.len);
+  return crt.raw.len;
+}
+
+char *CCertificate::GetPem() const
+{
+  if (!is_loaded)
+    {
+      return 0;
+    }
+
+  char pem_buf[1000];
+  size_t pem_content_size;
+  auto result = mbedtls_pem_write_buffer(
+      certificate_header, certificate_footer, crt.raw.p, crt.raw.len,
+      (uint8_t *)pem_buf, sizeof(pem_buf), &pem_content_size);
+  if (result != 0)
+    {
+      return nullptr;
+    }
+
+  auto pem = new char[pem_content_size + 1];
+  memcpy(pem, pem_buf, pem_content_size);
+  pem[pem_content_size] = 0;
+  return pem;
+}
+
+bool CCertificate::ContainsSan(const char *name, size_t size) const
+{
+  auto san_amount = GetNumberOfSubjectAlternativeNames();
+  for (size_t i = 0; i < san_amount; i++)
+    {
+      auto san = GetSubjectAlternativeName(i);
+      if (!san)
+        {
+          return false;
+        }
+      auto found = (memcmp(name, san, size) == 0);
+      delete[] san;
+      if (found)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+} // namespace Controlse
diff --git a/crypto/controlse/ccsr.cxx b/crypto/controlse/ccsr.cxx
new file mode 100644
index 000000000..e57f7b0d1
--- /dev/null
+++ b/crypto/controlse/ccsr.cxx
@@ -0,0 +1,212 @@
+//***************************************************************************
+// apps/crypto/controlse/ccsr.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include "crypto/controlse/ccsr.hxx"
+
+#include "cmbedtls_se05x_extension.hxx"
+#include "crypto/controlse/cpublic_key.hxx"
+#include "crypto/controlse/csecure_element.hxx"
+#include <cstring>
+#include <mbedtls/pem.h>
+
+using Controlse::MbedtlsSe05xExtension;
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Private Data
+//***************************************************************************
+
+static const char certificate_request_header[]
+    = "-----BEGIN CERTIFICATE REQUEST-----\n";
+static const char certificate_request_footer[]
+    = "-----END CERTIFICATE REQUEST-----\n";
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CCsr::CCsr(const ISecureElement &se, uint32_t keystore_id)
+{
+  mbedtls_x509_csr_init(&csr);
+  is_loaded = LoadFromSecureElement(se, keystore_id);
+}
+
+CCsr::CCsr(const uint8_t *der_or_pem, const size_t size)
+{
+  mbedtls_x509_csr_init(&csr);
+  is_loaded = 0 == mbedtls_x509_csr_parse(&csr, der_or_pem, size);
+}
+
+CCsr::~CCsr() { mbedtls_x509_csr_free(&csr); }
+
+bool CCsr::IsLoaded() const { return is_loaded; }
+
+bool CCsr::StoreOnSecureElement(const ISecureElement &se,
+                                uint32_t keystore_id) const
+{
+  struct se05x_key_transmission_s args;
+  args.entry.id = keystore_id;
+  args.content.buffer = csr.raw.p;
+  args.content.buffer_size = csr.raw.len;
+  args.content.buffer_content_size = csr.raw.len;
+  return se.SetData(args);
+}
+
+bool CCsr::LoadFromSecureElement(const ISecureElement &se,
+                                 uint32_t keystore_id)
+{
+  size_t csr_der_size = 1000;
+  uint8_t *csr_der = new uint8_t[csr_der_size];
+  struct se05x_key_transmission_s args
+      = { .entry = { .id = keystore_id },
+          .content = { .buffer = csr_der, .buffer_size = csr_der_size } };
+  bool result = se.GetData(args);
+
+  if (result)
+    {
+      result = 0
+               == mbedtls_x509_csr_parse(&csr, csr_der,
+                                         args.content.buffer_content_size);
+    }
+
+  delete[] csr_der;
+  return result;
+}
+
+size_t CCsr::GetDer(uint8_t **der) const
+{
+  if (!IsLoaded())
+    {
+      return 0;
+    }
+  *der = new uint8_t[csr.raw.len];
+  memcpy(*der, csr.raw.p, csr.raw.len);
+  return csr.raw.len;
+}
+
+char *CCsr::GetPem() const
+{
+  if (!IsLoaded())
+    {
+      return nullptr;
+    }
+
+  char pem_buf[1000];
+  size_t pem_content_size;
+  auto result = mbedtls_pem_write_buffer(
+      certificate_request_header, certificate_request_footer, csr.raw.p,
+      csr.raw.len, (uint8_t *)pem_buf, sizeof(pem_buf), &pem_content_size);
+  if (result != 0)
+    {
+      return nullptr;
+    }
+
+  auto pem = new char[pem_content_size + 1];
+  memcpy(pem, pem_buf, pem_content_size);
+  pem[pem_content_size] = 0;
+  return pem;
+}
+
+CCsr::CsrBuilder::CsrBuilder(ISecureElement &se, const char *subject,
+                             uint32_t key_slot_id)
+{
+  mbedtls_x509write_csr_init(&csr_w);
+  mbedtls_pk_init(&key);
+
+  ready = 0
+          == MbedtlsSe05xExtension::mbedtls_pk_setup_key_se05x(key, se,
+                                                               key_slot_id);
+
+  if (ready)
+    {
+      mbedtls_x509write_csr_set_key(&csr_w, &key);
+      ready = 0 == mbedtls_x509write_csr_set_subject_name(&csr_w, subject);
+    }
+
+  if (ready)
+    {
+      mbedtls_x509write_csr_set_md_alg(&csr_w, MBEDTLS_MD_SHA256);
+      ready = 0
+              == mbedtls_x509write_csr_set_key_usage(
+                  &csr_w, MBEDTLS_X509_KU_KEY_CERT_SIGN);
+    }
+}
+
+CCsr::CsrBuilder *CCsr::CsrBuilder::AddExtension(const char *oid,
+                                                 size_t oid_size,
+                                                 const uint8_t *value,
+                                                 size_t value_size)
+{
+  if (ready)
+    {
+      ready = 0
+              == mbedtls_x509write_csr_set_extension(&csr_w, oid, oid_size, 0,
+                                                     value, value_size);
+    }
+
+  return this;
+}
+
+CCsr *CCsr::CsrBuilder::Build()
+{
+  size_t buf_size = 1000;
+  uint8_t *buf = nullptr;
+  if (ready)
+    {
+      buf = new uint8_t[buf_size];
+      ready = nullptr != buf;
+    }
+
+  int write_result_size = 0;
+  if (ready)
+    {
+      write_result_size
+          = mbedtls_x509write_csr_der(&csr_w, buf, buf_size, nullptr, 0);
+      ready = write_result_size > 0;
+    }
+
+  MbedtlsSe05xExtension::mbedtls_pk_free_se05x(key);
+  mbedtls_x509write_csr_free(&csr_w);
+
+  CCsr *result_csr = nullptr;
+  if (ready)
+    {
+      result_csr
+          = new CCsr(buf + buf_size - write_result_size, write_result_size);
+    }
+
+  if (buf)
+    {
+      delete[] buf;
+    }
+
+  return result_csr;
+}
+
+} // namespace Controlse
diff --git a/crypto/controlse/chex_util.cxx b/crypto/controlse/chex_util.cxx
new file mode 100644
index 000000000..e2aebae76
--- /dev/null
+++ b/crypto/controlse/chex_util.cxx
@@ -0,0 +1,100 @@
+//***************************************************************************
+// apps/crypto/controlse/chex_util.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/chex_util.hxx"
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+size_t CHexUtil::GetByteArraySizeFromHexString(const char *hex_buffer)
+{
+  auto hex_buffer_size = strcspn(hex_buffer, " \r\n");
+  return GetByteArraySizeFromHexStringSize(hex_buffer_size);
+}
+
+size_t CHexUtil::GetByteArraySizeFromHexStringSize(size_t hex_buffer_size)
+{
+  return hex_buffer_size / AMOUNT_OF_HEXDIGITS_PER_BYTE;
+}
+
+size_t CHexUtil::GetHexStringSizeFromByteArraySize(size_t byte_array_size)
+{
+  return byte_array_size * AMOUNT_OF_HEXDIGITS_PER_BYTE;
+}
+
+uint8_t *CHexUtil::ConvertHexStringToByteArray(const char *hex_buffer)
+{
+  auto hex_buffer_size = strcspn(hex_buffer, " \r\n");
+  if (hex_buffer_size & 1)
+    {
+      return nullptr;
+    }
+
+  return ConvertHexStringToByteArray(hex_buffer, hex_buffer_size);
+}
+
+uint8_t *CHexUtil::ConvertHexStringToByteArray(const char *hex_buffer,
+                                               size_t hex_buffer_size)
+{
+  auto bin_buffer
+      = new uint8_t[GetByteArraySizeFromHexStringSize(hex_buffer_size)];
+  if (bin_buffer)
+    {
+      size_t hex_buffer_pos;
+      size_t bin_buffer_pos = 0;
+      for (hex_buffer_pos = 0; (hex_buffer_pos < hex_buffer_size);
+           hex_buffer_pos += AMOUNT_OF_HEXDIGITS_PER_BYTE)
+        {
+          sscanf(&hex_buffer[hex_buffer_pos], "%2hhx",
+                 &bin_buffer[bin_buffer_pos]);
+          bin_buffer_pos++;
+        }
+    }
+  return bin_buffer;
+}
+
+char *CHexUtil::ByteArrayToHexString(const uint8_t bytearray[], size_t size)
+{
+  auto string = new char[GetHexStringSizeFromByteArraySize(size) + 1];
+  if (string)
+    {
+      char *ptr = string;
+      for (size_t i = 0; i < size; i++)
+        {
+          ptr += sprintf(ptr, "%02x", bytearray[i]);
+        }
+    }
+  return string;
+}
+
+} // namespace Controlse
diff --git a/crypto/controlse/cmbedtls_se05x_extension.hxx b/crypto/controlse/cmbedtls_se05x_extension.hxx
new file mode 100644
index 000000000..9568ad667
--- /dev/null
+++ b/crypto/controlse/cmbedtls_se05x_extension.hxx
@@ -0,0 +1,188 @@
+//***************************************************************************
+// apps/crypto/controlse/cmbedtls_se05x_extensions.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include "crypto/controlse/cpublic_key.hxx"
+#include "crypto/controlse/isecure_element.hxx"
+#include <../crypto/mbedtls/mbedtls/library/pk_wrap.h>
+#include <cerrno>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/x509_csr.h>
+#include <nuttx/crypto/se05x.h>
+
+using Controlse::ISecureElement;
+
+struct mbedtls_se05x_ctx
+{
+  const ISecureElement *se;
+  uint32_t private_key_slot_id;
+};
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class MbedtlsSe05xExtension
+{
+public:
+  static int mbedtls_pk_parse_se05x_public_key(mbedtls_pk_context &key,
+                                               CPublicKey &se05x_key)
+  {
+    mbedtls_ecp_keypair *keypair;
+    uint8_t *key_buffer = nullptr;
+    size_t key_buffer_size = 0;
+    if (se05x_key.IsLoaded())
+      {
+        key_buffer_size = se05x_key.GetRawSize();
+        key_buffer = new uint8_t[key_buffer_size];
+        keypair = (mbedtls_ecp_keypair *)key.pk_ctx;
+      }
+
+    int result = -ENOMEM;
+    if (key_buffer)
+      {
+        se05x_key.GetRaw(key_buffer);
+        result
+            = mbedtls_ecp_group_load(&keypair->grp, MBEDTLS_ECP_DP_SECP256R1);
+      }
+
+    if (result == 0)
+      {
+        result = mbedtls_ecp_point_read_binary(&keypair->grp, &keypair->Q,
+                                               key_buffer, key_buffer_size);
+      }
+
+    if (key_buffer)
+      {
+        delete[] key_buffer;
+      }
+
+    return result;
+  }
+
+  static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             unsigned char *sig, size_t sig_size,
+                             size_t *sig_len,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
+  {
+
+    mbedtls_ecp_keypair *key = reinterpret_cast<mbedtls_ecp_keypair *>(ctx);
+    auto se05x_ctx = reinterpret_cast<mbedtls_se05x_ctx *>(key->d.p);
+
+    struct se05x_signature_s args
+        = { se05x_ctx->private_key_slot_id,
+            SE05X_ALGORITHM_SHA256,
+            { const_cast<uint8_t *>(hash), hash_len, hash_len },
+            { sig, sig_size, sig_size } };
+    auto result = se05x_ctx->se->CreateSignature(args);
+
+    if (result)
+      {
+        *sig_len = args.signature.buffer_content_size;
+      }
+
+    return result ? 0 : -EPERM;
+  }
+
+  // return value is allocated ptr to mbedtls_pk_info_t (need to be deleted)
+  // otherwise nulltpr
+  static mbedtls_pk_info_t *CreatePkInfoSe05x()
+  {
+    auto info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
+    auto se05x_ec_info = new mbedtls_pk_info_t;
+    if (se05x_ec_info)
+      {
+        *se05x_ec_info = *info;
+        se05x_ec_info->sign_func = ecdsa_sign_wrap;
+      }
+    return se05x_ec_info;
+  }
+
+  static int mbedtls_pk_setup_key_se05x(mbedtls_pk_context &key,
+                                        const ISecureElement &se,
+                                        uint32_t key_slot_id)
+  {
+    auto se05x_ec_info = CreatePkInfoSe05x();
+    if (se05x_ec_info)
+      {
+        key.pk_info = se05x_ec_info;
+        key.pk_ctx = se05x_ec_info->ctx_alloc_func();
+      }
+
+    int result = -ENOMEM;
+    if (key.pk_ctx)
+      {
+        auto se05x_key = CPublicKey(se, key_slot_id);
+        result = mbedtls_pk_parse_se05x_public_key(key, se05x_key);
+      }
+
+    mbedtls_se05x_ctx *se05x_ctx = nullptr;
+    if (result == 0)
+      {
+        se05x_ctx = new mbedtls_se05x_ctx;
+        result = se05x_ctx ? 0 : -ENOMEM;
+      }
+
+    if (result == 0)
+      {
+        se05x_ctx->private_key_slot_id = key_slot_id;
+        se05x_ctx->se = &se;
+      }
+
+    ((mbedtls_ecp_keypair *)key.pk_ctx)->d.p
+        = reinterpret_cast<mbedtls_mpi_uint *>(se05x_ctx);
+    return result;
+  }
+
+  static void mbedtls_pk_free_se05x(mbedtls_pk_context &key)
+  {
+    auto key_ctx = reinterpret_cast<mbedtls_ecp_keypair *>(key.pk_ctx);
+    if (key_ctx)
+      {
+        auto se05x_ctx = reinterpret_cast<mbedtls_se05x_ctx *>(key_ctx->d.p);
+        if (se05x_ctx)
+          {
+            delete se05x_ctx;
+            key_ctx->d.p = nullptr;
+          }
+      }
+    auto pk_info = key.pk_info;
+    if (pk_info)
+      {
+        mbedtls_pk_free(&key);
+        delete pk_info;
+      }
+  }
+};
+} // namespace Controlse
diff --git a/crypto/controlse/controlse_main.c b/crypto/controlse/controlse_main.c
deleted file mode 100644
index f2ed327b8..000000000
--- a/crypto/controlse/controlse_main.c
+++ /dev/null
@@ -1,737 +0,0 @@
-/****************************************************************************
- * apps/crypto/controlse/controlse_main.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you 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.
- *
- ****************************************************************************/
-
-/* Copyright 2023 NXP */
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-#include <mbedtls/sha256.h>
-#include <mbedtls/x509_crt.h>
-#include <mbedtls/x509_csr.h>
-#include <nuttx/config.h>
-#include <nuttx/crypto/se05x.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#ifdef CONFIG_STACK_COLORATION
-#include <nuttx/arch.h>
-#include <nuttx/sched.h>
-#endif
-
-#include "x509_utils.h"
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-#define EOT 0x04
-
-#define DEFAULT_SETTINGS                                                     \
-  {                                                                          \
-    .se05x_dev_filename = default_se05x_device, 0                            \
-  }
-
-#define TBS_HASH_BUFFER_SIZE 32
-#define SIGNATURE_BUFFER_SIZE 300
-#define SYMM_KEY_BUFFER_SIZE 300
-#define RAW_KEY_BUFFER_SIZE 600
-#define DEFAULT_BUFFER_SIZE 1000
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-typedef enum
-{
-  KEYSTORE_NO_ACTION = 0,
-  KEYSTORE_READ,
-  KEYSTORE_WRITE,
-  KEYSTORE_GENERATE,
-  KEYSTORE_DELETE,
-  KEYSTORE_DERIVE_SYMM_KEY,
-  KEYSTORE_CREATE_SIGNATURE,
-  KEYSTORE_VERIFY_SIGNATURE,
-  KEYSTORE_SIGN_CSR,
-  KEYSTORE_VERIFY_CERTIFICATE,
-  KEYSTORE_GET_INFO,
-  KEYSTORE_GET_UID,
-} keystore_operation;
-
-struct settings_t
-{
-  FAR const char *se05x_dev_filename;
-  FAR char *input_filename;
-  FAR char *signature_filename;
-  bool skip_process;
-  keystore_operation operation;
-  bool raw_data_in_device;
-  bool interface_with_pem;
-  uint32_t key_id;
-  uint32_t private_key_id;
-  bool show_stack_used;
-};
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static const char default_se05x_device[] = "/dev/se05x";
-static const char enter_key_hex[] = "enter key(hex)";
-static const char enter_data_pem[] = "enter data(pem)";
-static const char enter_data_raw[] = "enter data(raw)";
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static void print_usage(FAR FILE *f, FAR char *prg)
-{
-  fprintf(f, "%s - Control SE05x Secure Element\n", prg);
-  fprintf(f, "\nUsage: %s [options] <secure element device>\n", prg);
-  fprintf(f, "Options:\n");
-  fprintf(f, "         -r <id>     (read item from keystore at <id>)\n");
-  fprintf(f, "         -w <id>     (set item in keystore at <id>)\n");
-  fprintf(f, "         -g <id>     (generate keypair at <id>)\n");
-  fprintf(f, "         -d <id>     (delete key at <id>)\n");
-  fprintf(f, "         -s <id>     (create signature for data\n");
-  fprintf(f, "                      with key at <id>)\n");
-  fprintf(f, "         -S <id>     (Sign CSR with key at <id>)\n");
-  fprintf(f, "         -v <id>     (verify signature for data\n");
-  fprintf(f, "                      with key at <id>)\n");
-  fprintf(f, "         -V <id>     (verify CRT with key at <id>\n");
-  fprintf(f, "         -a <id>     (derive symm key\n");
-  fprintf(f, "                      from public key <id>\n");
-  fprintf(f, "                      and private key)\n");
-  fprintf(f, "         -t          (interface using raw data\n");
-  fprintf(f, "                      use with -r, -w)\n");
-  fprintf(f, "         -c          (interface with PEM format\n");
-  fprintf(f, "                      internally using DER\n");
-  fprintf(f, "                      use with -r, -w)\n");
-  fprintf(f, "         -p <id>     (select private key\n");
-  fprintf(f, "                      use with -a)\n");
-  fprintf(f, "         -n <file>   (Read input from file)\n");
-  fprintf(f, "         -N <file>   (Read signature from file)\n");
-  fprintf(f, "         -i          (show generic information)\n");
-  fprintf(f, "         -u          (show UID)\n");
-  fprintf(f, "         -m          (show used stack memory space)\n");
-  fprintf(f, "         -h          (show this help)\n");
-  fprintf(f, "\n");
-}
-
-static int set_operation(FAR struct settings_t *settings,
-                         keystore_operation operation, FAR char *key_id_text)
-{
-  int result = -EPERM;
-  if (settings->operation == KEYSTORE_NO_ACTION)
-    {
-      settings->operation = operation;
-      settings->key_id = 0;
-      if (key_id_text != NULL)
-        {
-          settings->key_id = (uint32_t)strtoul(key_id_text, NULL, 0);
-        }
-
-      result = 0;
-    }
-
-  return result;
-}
-
-static int parse_arguments(int argc, FAR char *argv[],
-                           FAR struct settings_t *settings)
-{
-  int result = 0;
-  int opt;
-  FAR char *prg = basename(argv[0]);
-  while (
-      ((opt = getopt(argc, argv, "iug:w:r:d:s:v:S:V:tca:p:n:N:mh")) != -1) &&
-      (result == 0))
-    {
-      switch (opt)
-        {
-        case 'i':
-          result = set_operation(settings, KEYSTORE_GET_INFO, optarg);
-          break;
-        case 'u':
-          result = set_operation(settings, KEYSTORE_GET_UID, optarg);
-          break;
-        case 'g':
-          result = set_operation(settings, KEYSTORE_GENERATE, optarg);
-          break;
-        case 'r':
-          result = set_operation(settings, KEYSTORE_READ, optarg);
-          break;
-        case 'w':
-          result = set_operation(settings, KEYSTORE_WRITE, optarg);
-          break;
-        case 't':
-          settings->raw_data_in_device = TRUE;
-          break;
-        case 'c':
-          settings->interface_with_pem = TRUE;
-          settings->raw_data_in_device = TRUE;
-          break;
-        case 'd':
-          result = set_operation(settings, KEYSTORE_DELETE, optarg);
-          break;
-        case 's':
-          result =
-            set_operation(settings, KEYSTORE_CREATE_SIGNATURE, optarg);
-          break;
-        case 'v':
-          result =
-            set_operation(settings, KEYSTORE_VERIFY_SIGNATURE, optarg);
-          break;
-        case 'S':
-          result = set_operation(settings, KEYSTORE_SIGN_CSR, optarg);
-          break;
-        case 'V':
-          result =
-              set_operation(settings, KEYSTORE_VERIFY_CERTIFICATE, optarg);
-          break;
-        case 'a':
-          result = set_operation(settings, KEYSTORE_DERIVE_SYMM_KEY, optarg);
-          break;
-        case 'p':
-          settings->private_key_id = (uint32_t)strtoul(optarg, NULL, 0);
-          break;
-        case 'n':
-          settings->input_filename = optarg;
-          break;
-        case 'N':
-          settings->signature_filename = optarg;
-          break;
-        case 'm':
-          settings->show_stack_used = TRUE;
-          break;
-        case 'h':
-          print_usage(stdout, prg);
-          settings->skip_process = TRUE;
-          break;
-        default:
-          print_usage(stderr, prg);
-          result = -EINVAL;
-          break;
-        }
-    }
-
-  if ((result == 0) && (!settings->skip_process))
-    {
-      if (settings->operation == KEYSTORE_NO_ACTION)
-        {
-          print_usage(stderr, prg);
-          result = -EINVAL;
-        }
-
-      /* if device is specified as positional argument */
-
-      if (optind != argc)
-        {
-          settings->se05x_dev_filename = argv[optind];
-        }
-    }
-
-  return result;
-}
-
-static int convert_array_hex_to_bin(FAR char *hex_buffer,
-                                    size_t hex_buffer_size,
-                                    FAR uint8_t *bin_buffer,
-                                    size_t bin_buffer_size,
-                                    FAR size_t *bin_buffer_content_size)
-{
-  hex_buffer_size = strcspn(hex_buffer, " \r\n");
-  if (hex_buffer_size & 1)
-    {
-      return -1;
-    }
-
-  *bin_buffer_content_size = 0;
-  size_t hex_buffer_pos;
-  for (hex_buffer_pos = 0; (hex_buffer_pos < hex_buffer_size) &&
-                           (*bin_buffer_content_size < bin_buffer_size);
-       hex_buffer_pos += 2)
-    {
-      sscanf(&hex_buffer[hex_buffer_pos], "%2hhx",
-             &bin_buffer[*bin_buffer_content_size]);
-      (*bin_buffer_content_size)++;
-    }
-
-  return hex_buffer_pos == hex_buffer_size ? 0 : -1;
-}
-
-static int read_from_file(FAR const char *prompt, FAR char *filename,
-                          FAR char *buffer, size_t buffer_size)
-{
-  FAR FILE *f = stdin;
-  if (filename != NULL)
-    {
-      f = fopen(filename, "r");
-    }
-  else
-    {
-      puts(prompt);
-    }
-
-  size_t buffer_content_size = 0;
-  if (f != NULL)
-    {
-      FAR char *c = buffer;
-      int result = fgetc(f);
-      while ((result != EOF) && (result != EOT) &&
-             (buffer_content_size < buffer_size))
-        {
-          *c = result & 0xff;
-          c++;
-          buffer_content_size++;
-          result = fgetc(f);
-        }
-    }
-
-  if (filename != NULL)
-    {
-      fclose(f);
-    }
-
-  return buffer_content_size;
-}
-
-static int read_from_file_and_convert(FAR const char *prompt,
-                                      FAR char *filename,
-                                      FAR uint8_t *buffer,
-                                      size_t buffer_size,
-                                      FAR size_t *buffer_content_size)
-{
-  char file_buffer[DEFAULT_BUFFER_SIZE];
-  size_t file_buffer_content_size;
-  int result;
-
-  file_buffer_content_size = read_from_file(
-      prompt, filename, (FAR char *)file_buffer, sizeof(file_buffer));
-  result = convert_array_hex_to_bin(file_buffer, file_buffer_content_size,
-                                    buffer, buffer_size, buffer_content_size
-                                    );
-
-  return result;
-}
-
-static size_t add_zero_termination_character(char *data, size_t content_size,
-                                             size_t buf_size)
-{
-  size_t zero_termination_char_position = content_size - 1;
-  if ((content_size + 1) <= buf_size)
-    {
-      zero_termination_char_position = content_size;
-      content_size++;
-    }
-
-  data[zero_termination_char_position] = 0;
-  return content_size;
-}
-
-static int process(int se05x_fd, FAR struct settings_t *settings)
-{
-  int result = 0;
-  if (settings->operation == KEYSTORE_GET_INFO)
-    {
-      struct se05x_info_s info;
-      result = ioctl(se05x_fd, SEIOC_GET_INFO, &info);
-
-      if (result == 0)
-        {
-          printf("OEF ID: %04x\n", info.oef_id);
-        }
-    }
-
-  else if (settings->operation == KEYSTORE_GET_UID)
-    {
-      struct se05x_uid_s uid;
-      result = ioctl(se05x_fd, SEIOC_GET_UID, &uid);
-
-      if (result == 0)
-        {
-          printf("UID: ");
-          for (size_t i = 0; i < SE05X_MODULE_UNIQUE_ID_LEN; i++)
-            {
-              printf("%02x", uid.uid[i]);
-            }
-
-          printf("\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_GENERATE)
-    {
-      struct se05x_generate_keypair_s args = {
-          .id = settings->key_id, .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256
-      };
-
-      result = ioctl(se05x_fd, SEIOC_GENERATE_KEYPAIR, &args);
-
-      if (result == 0)
-        {
-          printf("Keypair generated successfully\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_WRITE)
-    {
-      char pem_buf[DEFAULT_BUFFER_SIZE];
-      FAR const char *prompt = enter_key_hex;
-      if (settings->raw_data_in_device)
-        {
-          prompt =
-              settings->interface_with_pem ? enter_data_pem : enter_data_raw;
-        }
-
-      size_t pem_content_size = read_from_file(
-          prompt, settings->input_filename, pem_buf, sizeof(pem_buf));
-
-      uint8_t rawkey[RAW_KEY_BUFFER_SIZE];
-      size_t rawkey_size = sizeof(rawkey);
-
-      FAR uint8_t *data = (FAR uint8_t *)pem_buf;
-      size_t data_size = pem_content_size;
-      if (!settings->raw_data_in_device)
-        {
-          result = convert_public_key_pem_to_raw(rawkey, rawkey_size,
-                                                 &rawkey_size, pem_buf);
-          if (result == 0)
-            {
-              data = rawkey;
-              data_size = rawkey_size;
-            }
-        }
-
-      if (settings->interface_with_pem)
-        {
-          pem_content_size = add_zero_termination_character(
-              pem_buf, pem_content_size, sizeof(pem_buf));
-          result = convert_pem_certificate_or_csr_to_der(
-              rawkey, rawkey_size, &rawkey_size, pem_buf, pem_content_size);
-          if (result == 0)
-            {
-              data = rawkey;
-              data_size = rawkey_size;
-            }
-        }
-
-      if (result == 0)
-        {
-          struct se05x_key_transmission_s args = {
-              .entry = {.id = settings->key_id,
-                        .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256},
-              .content = {.buffer = data,
-                          .buffer_size = data_size,
-                          .buffer_content_size = data_size}
-          };
-
-          result = ioctl(se05x_fd,
-                         settings->raw_data_in_device ? SEIOC_SET_DATA
-                                                      : SEIOC_SET_KEY,
-                         &args);
-        }
-
-      if (result == 0)
-        {
-          printf("Data stored successfully\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_READ)
-    {
-      uint8_t buffer[DEFAULT_BUFFER_SIZE];
-      struct se05x_key_transmission_s args = {
-          .entry = {.id = settings->key_id},
-          .content = {.buffer = buffer, .buffer_size = sizeof(buffer)}
-      };
-
-      result =
-        ioctl(se05x_fd,
-              settings->raw_data_in_device ? SEIOC_GET_DATA : SEIOC_GET_KEY,
-              &args);
-
-      FAR char *data = (FAR char *)args.content.buffer;
-      if ((result == 0)
-              && settings->raw_data_in_device
-              && !settings->interface_with_pem)
-        {
-          args.content.buffer_content_size = add_zero_termination_character(
-              data, args.content.buffer_content_size,
-              args.content.buffer_size);
-        }
-
-      char pem_buf[DEFAULT_BUFFER_SIZE];
-      if ((result == 0) && !settings->raw_data_in_device)
-        {
-          result = convert_public_key_raw_to_pem(
-              pem_buf, sizeof(pem_buf), args.content.buffer,
-              args.content.buffer_content_size);
-
-          data = pem_buf;
-        }
-
-      if ((result == 0) && settings->interface_with_pem)
-        {
-          size_t pem_content_size;
-          result = convert_der_certificate_or_csr_to_pem(
-              pem_buf, sizeof(pem_buf), &pem_content_size,
-              args.content.buffer, args.content.buffer_content_size);
-
-          data = pem_buf;
-        }
-
-      if (result == 0)
-        {
-          puts(data);
-        }
-    }
-  else if (settings->operation == KEYSTORE_DELETE)
-    {
-      result = ioctl(se05x_fd, SEIOC_DELETE_KEY, settings->key_id);
-
-      if (result == 0)
-        {
-          printf("Deleted key successfully\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_DERIVE_SYMM_KEY)
-    {
-      uint8_t buffer[SYMM_KEY_BUFFER_SIZE];
-      struct se05x_derive_key_s args = {
-          .private_key_id = settings->private_key_id,
-          .public_key_id = settings->key_id,
-          .content = {.buffer = buffer, .buffer_size = sizeof(buffer)},
-      };
-
-      result = ioctl(se05x_fd, SEIOC_DERIVE_SYMM_KEY, &args);
-
-      if (result == 0)
-        {
-          for (size_t i = 0; i < args.content.buffer_content_size; i++)
-            {
-              printf("%02x", args.content.buffer[i]);
-            }
-
-          printf("\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_CREATE_SIGNATURE)
-    {
-      uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
-      size_t tbs_content_size;
-      read_from_file_and_convert("Enter tbs(hex):", settings->input_filename,
-                                 tbs_buffer, sizeof(tbs_buffer),
-                                 &tbs_content_size);
-      uint8_t signature_buffer[SIGNATURE_BUFFER_SIZE];
-      size_t signature_content_len = 0;
-      if (result == 0)
-        {
-          struct se05x_signature_s args = {
-              .key_id = settings->key_id,
-              .algorithm = SE05X_ALGORITHM_SHA256,
-              .tbs = {.buffer = tbs_buffer,
-                      .buffer_size = tbs_content_size,
-                      .buffer_content_size = tbs_content_size},
-              .signature = {.buffer = signature_buffer,
-                            .buffer_size = sizeof(signature_buffer)},
-          };
-
-          result = ioctl(se05x_fd, SEIOC_CREATE_SIGNATURE, &args);
-          signature_content_len = args.signature.buffer_content_size;
-        }
-
-      if (result == 0)
-        {
-          for (size_t i = 0; i < signature_content_len; i++)
-            {
-              printf("%02x", signature_buffer[i]);
-            }
-
-          printf("\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_VERIFY_SIGNATURE)
-    {
-      uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
-      size_t tbs_content_size;
-      result = read_from_file_and_convert(
-          "Enter tbs(hex):", settings->input_filename, tbs_buffer,
-          sizeof(tbs_buffer), &tbs_content_size);
-
-      uint8_t signature_buffer[SIGNATURE_BUFFER_SIZE];
-      size_t signature_content_size;
-      if (result == 0)
-        {
-          result = read_from_file_and_convert(
-              "Enter signature(hex):", settings->signature_filename,
-              signature_buffer, sizeof(signature_buffer),
-              &signature_content_size);
-        }
-
-      if (result == 0)
-        {
-          struct se05x_signature_s args = {
-              .key_id = settings->key_id,
-              .algorithm = SE05X_ALGORITHM_SHA256,
-              .tbs = {.buffer = tbs_buffer,
-                      .buffer_size = tbs_content_size,
-                      .buffer_content_size = tbs_content_size},
-              .signature = {.buffer = signature_buffer,
-                            .buffer_size = signature_content_size,
-                            .buffer_content_size = signature_content_size},
-          };
-
-          result = ioctl(se05x_fd, SEIOC_VERIFY_SIGNATURE, &args);
-        }
-
-      if (result == 0)
-        {
-          printf("Signature verified successfully\n");
-        }
-    }
-  else if (settings->operation == KEYSTORE_SIGN_CSR)
-    {
-      char csr_pem_buf[DEFAULT_BUFFER_SIZE];
-      size_t csr_pem_buf_content_size =
-          read_from_file("enter csr(pem)", settings->input_filename,
-                         csr_pem_buf, sizeof(csr_pem_buf));
-
-      csr_pem_buf_content_size = add_zero_termination_character(csr_pem_buf,
-              csr_pem_buf_content_size, sizeof(csr_pem_buf));
-
-      char crt_pem_buf[DEFAULT_BUFFER_SIZE];
-      result = sign_csr(se05x_fd, settings->key_id, crt_pem_buf,
-                        sizeof(crt_pem_buf), csr_pem_buf,
-                        csr_pem_buf_content_size);
-      if (result == 0)
-        {
-          puts(crt_pem_buf);
-        }
-    }
-  else if (settings->operation == KEYSTORE_VERIFY_CERTIFICATE)
-    {
-      char pem_buf[DEFAULT_BUFFER_SIZE];
-      size_t pem_content_size =
-          read_from_file("enter crt(pem)", settings->input_filename, pem_buf,
-                         sizeof(pem_buf));
-
-      pem_content_size = add_zero_termination_character(pem_buf,
-                                  pem_content_size, sizeof(pem_buf));
-
-      mbedtls_x509_crt crt;
-      mbedtls_x509_crt_init(&crt);
-      result = mbedtls_x509_crt_parse(&crt, (FAR uint8_t *)pem_buf,
-                                      pem_content_size);
-
-      uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
-
-      if (result == 0)
-        {
-          result = mbedtls_sha256(crt.tbs.p,
-                                  crt.tbs.len, tbs_buffer, 0
-                                  );
-        }
-
-      if (result == 0)
-        {
-          struct se05x_signature_s args = {
-              .key_id = settings->key_id,
-              .algorithm = SE05X_ALGORITHM_SHA256,
-              .tbs = {.buffer = tbs_buffer,
-                      .buffer_size = sizeof(tbs_buffer),
-                      .buffer_content_size = sizeof(tbs_buffer)},
-              .signature = {.buffer = crt.sig.p,
-                            .buffer_size = crt.sig.len,
-                            .buffer_content_size =
-                                crt.sig.len},
-          };
-
-          result = ioctl(se05x_fd, SEIOC_VERIFY_SIGNATURE, &args);
-        }
-
-      if (result == 0)
-        {
-          printf("Signature verified successfully\n");
-        }
-
-      mbedtls_x509_crt_free(&crt);
-    }
-
-  return result;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-int main(int argc, FAR char *argv[])
-{
-  struct settings_t settings = DEFAULT_SETTINGS;
-  int result = parse_arguments(argc, argv, &settings);
-
-  if ((result == 0) && (!settings.skip_process))
-    {
-      int fd = open(settings.se05x_dev_filename, O_RDONLY);
-      if (fd == -1)
-        {
-          result = -ENODEV;
-        }
-      else
-        {
-          result = process(fd, &settings);
-          close(fd);
-        }
-    }
-
-  if (result != 0)
-    {
-      fprintf(stderr, "err %i: %s\n", -result, strerror(-result));
-    }
-
-  if (settings.show_stack_used)
-    {
-#ifdef CONFIG_STACK_COLORATION
-      FAR struct tcb_s *tcb;
-      tcb = nxsched_get_tcb(getpid());
-      fprintf(stderr, "\nStack used: %zu / %zu\n",
-              up_check_tcbstack(tcb), tcb->adj_stack_size);
-#else
-      fprintf(stderr, "\nStack used: unknown"
-             " (STACK_COLORATION must be enabled)\n");
-#endif
-    }
-
-  return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/crypto/controlse/controlse_main.cxx b/crypto/controlse/controlse_main.cxx
new file mode 100644
index 000000000..238a85233
--- /dev/null
+++ b/crypto/controlse/controlse_main.cxx
@@ -0,0 +1,711 @@
+//***************************************************************************
+// apps/crypto/controlse/controlse_main.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2023, 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/ccertificate.hxx"
+#include "crypto/controlse/ccsr.hxx"
+#include "crypto/controlse/chex_util.hxx"
+#include "crypto/controlse/cpublic_key.hxx"
+#include "crypto/controlse/csecure_element.hxx"
+#include "crypto/controlse/cstring.hxx"
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <nuttx/config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#ifdef CONFIG_STACK_COLORATION
+#include <nuttx/arch.h>
+#include <nuttx/sched.h>
+#endif
+
+//***************************************************************************
+// Pre-processor Definitions
+//**************************************************************************
+
+#define EOT 0x04
+
+#define DEFAULT_SETTINGS                                                      \
+  {                                                                           \
+    .se05x_dev_filename = default_se05x_device, 0                             \
+  }
+
+#define TBS_HASH_BUFFER_SIZE 32
+#define SIGNATURE_BUFFER_SIZE 300
+#define SYMM_KEY_BUFFER_SIZE 300
+#define RAW_KEY_BUFFER_SIZE 600
+#define DEFAULT_BUFFER_SIZE 1000
+
+//***************************************************************************
+// Private Types
+//**************************************************************************
+
+typedef enum
+{
+  KEYSTORE_NO_ACTION = 0,
+  KEYSTORE_READ,
+  KEYSTORE_WRITE,
+  KEYSTORE_GENERATE,
+  KEYSTORE_DELETE,
+  KEYSTORE_DERIVE_SYMM_KEY,
+  KEYSTORE_CREATE_SIGNATURE,
+  KEYSTORE_VERIFY_SIGNATURE,
+  KEYSTORE_SIGN_CSR,
+  KEYSTORE_VERIFY_CERTIFICATE,
+  KEYSTORE_GET_INFO,
+  KEYSTORE_GET_UID,
+} EKeystoreOperation;
+
+typedef enum
+{
+  KEYSTORE_DATA_TYPE_KEY = 0,
+  KEYSTORE_DATA_TYPE_CERT_OR_CSR,
+  KEYSTORE_DATA_TYPE_STRING,
+} EKeystoreDataType;
+
+struct SSettings
+{
+  FAR const char *se05x_dev_filename;
+  FAR char *input_filename;
+  FAR char *signature_filename;
+  bool skip_process;
+  EKeystoreOperation operation;
+  EKeystoreDataType data_type;
+  uint32_t key_id;
+  uint32_t private_key_id;
+  bool show_stack_used;
+};
+
+//***************************************************************************
+// Private Function Prototypes
+//**************************************************************************
+
+extern "C" int main(int argc, FAR char *argv[]);
+
+//***************************************************************************
+// Private Data
+//**************************************************************************
+
+static const char default_se05x_device[] = "/dev/se05x";
+static const char enter_key_hex[] = "enter key(hex)";
+static const char enter_data_pem[] = "enter data(pem)";
+static const char enter_data_raw[] = "enter data(raw)";
+
+//***************************************************************************
+// Public Data
+//**************************************************************************
+
+//***************************************************************************
+// Private Functions
+//**************************************************************************
+
+static void printUsage(FAR FILE *f, FAR char *prg)
+{
+  fprintf(f, "%s - Control SE05x Secure Element\n", prg);
+  fprintf(f, "\nUsage: %s [options] <secure element device>\n", prg);
+  fprintf(f, "Options:\n");
+  fprintf(f, "         -r <id>     (read item from keystore at <id>)\n");
+  fprintf(f, "         -w <id>     (set item in keystore at <id>)\n");
+  fprintf(f, "         -g <id>     (generate keypair at <id>)\n");
+  fprintf(f, "         -d <id>     (delete key at <id>)\n");
+  fprintf(f, "         -s <id>     (create signature for data\n");
+  fprintf(f, "                      with key at <id>)\n");
+  fprintf(f, "         -S <id>     (Sign CSR with key at <id>)\n");
+  fprintf(f, "         -v <id>     (verify signature for data\n");
+  fprintf(f, "                      with key at <id>)\n");
+  fprintf(f, "         -V <id>     (verify CRT with key at <id>\n");
+  fprintf(f, "         -a <id>     (derive symm key\n");
+  fprintf(f, "                      from public key <id>\n");
+  fprintf(f, "                      and private key)\n");
+  fprintf(f, "         -t          (interface using raw data\n");
+  fprintf(f, "                      use with -r, -w)\n");
+  fprintf(f, "         -c          (interface with PEM format\n");
+  fprintf(f, "                      internally using DER\n");
+  fprintf(f, "                      use with -r, -w)\n");
+  fprintf(f, "         -p <id>     (select private key\n");
+  fprintf(f, "                      use with -a)\n");
+  fprintf(f, "         -n <file>   (Read input from file)\n");
+  fprintf(f, "         -N <file>   (Read signature from file)\n");
+  fprintf(f, "         -i          (show generic information)\n");
+  fprintf(f, "         -u          (show UID)\n");
+  fprintf(f, "         -m          (show used stack memory space)\n");
+  fprintf(f, "         -h          (show this help)\n");
+  fprintf(f, "\n");
+}
+
+static int setOperation(FAR struct SSettings *settings,
+                        EKeystoreOperation operation, FAR char *key_id_text)
+{
+  int result = -EPERM;
+  if (settings->operation == KEYSTORE_NO_ACTION)
+    {
+      settings->operation = operation;
+      settings->key_id = 0;
+      if (key_id_text != NULL)
+        {
+          settings->key_id = (uint32_t)strtoul(key_id_text, NULL, 0);
+        }
+
+      result = 0;
+    }
+
+  return result;
+}
+
+static int parseArguments(int argc, FAR char *argv[],
+                          FAR struct SSettings *settings)
+{
+  int result = 0;
+  int opt;
+  FAR char *prg = basename(argv[0]);
+  while (((opt = getopt(argc, argv, "iug:w:r:d:s:v:S:V:tca:p:n:N:mh")) != -1)
+         && (result == 0))
+    {
+      switch (opt)
+        {
+        case 'i':
+          result = setOperation(settings, KEYSTORE_GET_INFO, optarg);
+          break;
+        case 'u':
+          result = setOperation(settings, KEYSTORE_GET_UID, optarg);
+          break;
+        case 'g':
+          result = setOperation(settings, KEYSTORE_GENERATE, optarg);
+          break;
+        case 'r':
+          result = setOperation(settings, KEYSTORE_READ, optarg);
+          break;
+        case 'w':
+          result = setOperation(settings, KEYSTORE_WRITE, optarg);
+          break;
+        case 't':
+          settings->data_type = KEYSTORE_DATA_TYPE_STRING;
+          break;
+        case 'c':
+          settings->data_type = KEYSTORE_DATA_TYPE_CERT_OR_CSR;
+          break;
+        case 'd':
+          result = setOperation(settings, KEYSTORE_DELETE, optarg);
+          break;
+        case 's':
+          result = setOperation(settings, KEYSTORE_CREATE_SIGNATURE, optarg);
+          break;
+        case 'v':
+          result = setOperation(settings, KEYSTORE_VERIFY_SIGNATURE, optarg);
+          break;
+        case 'S':
+          result = setOperation(settings, KEYSTORE_SIGN_CSR, optarg);
+          break;
+        case 'V':
+          result = setOperation(settings, KEYSTORE_VERIFY_CERTIFICATE, optarg);
+          break;
+        case 'a':
+          result = setOperation(settings, KEYSTORE_DERIVE_SYMM_KEY, optarg);
+          break;
+        case 'p':
+          settings->private_key_id = (uint32_t)strtoul(optarg, NULL, 0);
+          break;
+        case 'n':
+          settings->input_filename = optarg;
+          break;
+        case 'N':
+          settings->signature_filename = optarg;
+          break;
+        case 'm':
+          settings->show_stack_used = TRUE;
+          break;
+        case 'h':
+          printUsage(stdout, prg);
+          settings->skip_process = TRUE;
+          break;
+        default:
+          printUsage(stderr, prg);
+          result = -EINVAL;
+          break;
+        }
+    }
+
+  if ((result == 0) && (!settings->skip_process))
+    {
+      if (settings->operation == KEYSTORE_NO_ACTION)
+        {
+          printUsage(stderr, prg);
+          result = -EINVAL;
+        }
+
+      // if device is specified as positional argument
+
+      if (optind != argc)
+        {
+          settings->se05x_dev_filename = argv[optind];
+        }
+    }
+
+  return result;
+}
+
+// TODO: use chexutil
+static int convert_array_hex_to_bin(FAR char *hex_buffer,
+                                    size_t hex_buffer_size,
+                                    FAR uint8_t *bin_buffer,
+                                    size_t bin_buffer_size,
+                                    FAR size_t *bin_buffer_content_size)
+{
+  hex_buffer_size = strcspn(hex_buffer, " \r\n");
+  if (hex_buffer_size & 1)
+    {
+      return -1;
+    }
+
+  *bin_buffer_content_size = 0;
+  size_t hex_buffer_pos;
+  for (hex_buffer_pos = 0; (hex_buffer_pos < hex_buffer_size)
+                           && (*bin_buffer_content_size < bin_buffer_size);
+       hex_buffer_pos += 2)
+    {
+      sscanf(&hex_buffer[hex_buffer_pos], "%2hhx",
+             &bin_buffer[*bin_buffer_content_size]);
+      (*bin_buffer_content_size)++;
+    }
+
+  return hex_buffer_pos == hex_buffer_size ? 0 : -1;
+}
+
+static int readFromFile(FAR const char *prompt, FAR char *filename,
+                        FAR char *buffer, size_t buffer_size)
+{
+  FAR FILE *f = stdin;
+  if (filename != NULL)
+    {
+      f = fopen(filename, "r");
+    }
+  else
+    {
+      puts(prompt);
+    }
+
+  size_t buffer_content_size = 0;
+  if (f != NULL)
+    {
+      FAR char *c = buffer;
+      int result = fgetc(f);
+      // keep looping until EOF or EOT are received or the buffer has only 1
+      // space left (needed for the zero termination character)
+      while ((result != EOF) && (result != EOT)
+             && ((buffer_content_size + 1) < buffer_size))
+        {
+          *c = result & 0xff;
+          c++;
+          buffer_content_size++;
+          result = fgetc(f);
+        }
+      // Add zero termination character
+      *c = 0;
+      buffer_content_size++;
+    }
+
+  puts("\n");
+
+  if (filename != NULL)
+    {
+      fclose(f);
+    }
+
+  return buffer_content_size;
+}
+
+static int readFromFileAndConvert(FAR const char *prompt, FAR char *filename,
+                                  FAR uint8_t *buffer, size_t buffer_size,
+                                  FAR size_t *buffer_content_size)
+{
+  char file_buffer[DEFAULT_BUFFER_SIZE];
+  size_t file_buffer_content_size;
+  int result;
+
+  file_buffer_content_size = readFromFile(
+      prompt, filename, (FAR char *)file_buffer, sizeof(file_buffer));
+  result = convert_array_hex_to_bin(file_buffer, file_buffer_content_size,
+                                    buffer, buffer_size, buffer_content_size);
+
+  return result;
+}
+
+static size_t addZeroTerminationCharacter(char *data, size_t content_size,
+                                          size_t buf_size)
+{
+  size_t zero_termination_char_position = content_size - 1;
+  if ((content_size + 1) <= buf_size)
+    {
+      zero_termination_char_position = content_size;
+      content_size++;
+    }
+
+  data[zero_termination_char_position] = 0;
+  return content_size;
+}
+
+static int process(int se05x_fd, FAR struct SSettings *settings)
+{
+  int result = 0;
+  Controlse::CSecureElement se(se05x_fd);
+  if (settings->operation == KEYSTORE_GET_INFO)
+    {
+      struct se05x_info_s info;
+      result = se.GetInfo(info) ? 0 : -EPERM;
+
+      if (result == 0)
+        {
+          printf("OEF ID: %04x\n", info.oef_id);
+        }
+    }
+  else if (settings->operation == KEYSTORE_GET_UID)
+    {
+      struct se05x_uid_s uid;
+      result = se.GetUid(uid) ? 0 : -EPERM;
+      if (result == 0)
+        {
+          printf("UID: ");
+          for (size_t i = 0; i < SE05X_MODULE_UNIQUE_ID_LEN; i++)
+            {
+              printf("%02x", uid.uid[i]);
+            }
+
+          printf("\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_GENERATE)
+    {
+      struct se05x_generate_keypair_s args
+          = { .id = settings->key_id,
+              .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256 };
+
+      result = se.GenerateKey(args) ? 0 : -EPERM;
+
+      if (result == 0)
+        {
+          printf("Keypair generated successfully\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_WRITE)
+    {
+      char data[DEFAULT_BUFFER_SIZE];
+      FAR const char *prompt = settings->data_type == KEYSTORE_DATA_TYPE_STRING
+                                   ? enter_data_raw
+                                   : enter_data_pem;
+
+      size_t data_size
+          = readFromFile(prompt, settings->input_filename, data, sizeof(data));
+
+      result = -EINVAL;
+      if (data_size != 0)
+        {
+          Controlse::ISecureElementObject *object = nullptr;
+          if (settings->data_type == KEYSTORE_DATA_TYPE_STRING)
+            {
+              object = new Controlse::CString(
+                  data,
+                  data_size - 1); // -1 because no zero termination character
+                                  // required
+            }
+          else if (settings->data_type == KEYSTORE_DATA_TYPE_KEY)
+            {
+              object = new Controlse::CPublicKey(data);
+            }
+          else if (settings->data_type == KEYSTORE_DATA_TYPE_CERT_OR_CSR)
+            {
+              object = new Controlse::CCertificate(
+                  reinterpret_cast<uint8_t *>(data), data_size);
+              if (object)
+                {
+                  if (!object->IsLoaded())
+                    {
+                      delete object;
+                      object = new Controlse::CCsr(
+                          reinterpret_cast<uint8_t *>(data), data_size);
+                    }
+                }
+            }
+
+          result = -EPERM;
+          if (object)
+            {
+              if (object->IsLoaded())
+                {
+                  result = object->StoreOnSecureElement(se, settings->key_id)
+                               ? 0
+                               : -EPERM;
+                }
+              delete object;
+            }
+        }
+
+      if (result == 0)
+        {
+          printf("Data stored successfully\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_READ)
+    {
+      char *data = nullptr;
+      if (settings->data_type == KEYSTORE_DATA_TYPE_STRING)
+        {
+          Controlse::CString string(se, settings->key_id);
+          if (string.IsLoaded())
+            {
+              data = string.c_str();
+            }
+        }
+      else if (settings->data_type == KEYSTORE_DATA_TYPE_KEY)
+        {
+          Controlse::CPublicKey key(se, settings->key_id);
+          if (key.IsLoaded())
+            {
+              data = key.GetPem();
+            }
+        }
+      else if (settings->data_type == KEYSTORE_DATA_TYPE_CERT_OR_CSR)
+        {
+          Controlse::CCertificate cert(se, settings->key_id);
+          if (cert.IsLoaded())
+            {
+              data = cert.GetPem();
+            }
+          else
+            {
+              Controlse::CCsr csr(se, settings->key_id);
+              if (csr.IsLoaded())
+                {
+                  data = csr.GetPem();
+                }
+            }
+        }
+      if (data)
+        {
+          puts(data);
+          delete[] data;
+        }
+      else
+        {
+          result = -EPERM;
+        }
+    }
+  else if (settings->operation == KEYSTORE_DELETE)
+    {
+      result = se.DeleteKey(settings->key_id) ? 0 : -EPERM;
+      if (result == 0)
+        {
+          printf("Deleted key successfully\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_DERIVE_SYMM_KEY)
+    {
+      uint8_t buffer[SYMM_KEY_BUFFER_SIZE];
+      struct se05x_derive_key_s args = {
+        .private_key_id = settings->private_key_id,
+        .public_key_id = settings->key_id,
+        .content = { .buffer = buffer, .buffer_size = sizeof(buffer) },
+      };
+
+      result = se.DeriveSymmetricalKey(args) ? 0 : -EPERM;
+
+      if (result == 0)
+        {
+          for (size_t i = 0; i < args.content.buffer_content_size; i++)
+            {
+              printf("%02x", args.content.buffer[i]);
+            }
+          printf("\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_CREATE_SIGNATURE)
+    {
+      uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
+      size_t tbs_content_size;
+      readFromFileAndConvert("Enter tbs(hex):", settings->input_filename,
+                             tbs_buffer, sizeof(tbs_buffer),
+                             &tbs_content_size);
+      uint8_t signature_buffer[SIGNATURE_BUFFER_SIZE];
+      size_t signature_content_len = 0;
+      if (result == 0)
+        {
+          struct se05x_signature_s args = {
+            .key_id = settings->key_id,
+            .algorithm = SE05X_ALGORITHM_SHA256,
+            .tbs = { .buffer = tbs_buffer,
+                     .buffer_size = tbs_content_size,
+                     .buffer_content_size = tbs_content_size },
+            .signature = { .buffer = signature_buffer,
+                           .buffer_size = sizeof(signature_buffer) },
+          };
+
+          result = se.CreateSignature(args) ? 0 : -EPERM;
+          signature_content_len = args.signature.buffer_content_size;
+        }
+
+      if (result == 0)
+        {
+          for (size_t i = 0; i < signature_content_len; i++)
+            {
+              printf("%02x", signature_buffer[i]);
+            }
+
+          printf("\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_VERIFY_SIGNATURE)
+    {
+      uint8_t tbs_buffer[TBS_HASH_BUFFER_SIZE];
+      size_t tbs_content_size;
+      result = readFromFileAndConvert(
+          "Enter tbs(hex):", settings->input_filename, tbs_buffer,
+          sizeof(tbs_buffer), &tbs_content_size);
+
+      uint8_t signature_buffer[SIGNATURE_BUFFER_SIZE];
+      size_t signature_content_size;
+      if (result == 0)
+        {
+          result = readFromFileAndConvert(
+              "Enter signature(hex):", settings->signature_filename,
+              signature_buffer, sizeof(signature_buffer),
+              &signature_content_size);
+        }
+
+      if (result == 0)
+        {
+          struct se05x_signature_s args = {
+            .key_id = settings->key_id,
+            .algorithm = SE05X_ALGORITHM_SHA256,
+            .tbs = { .buffer = tbs_buffer,
+                     .buffer_size = tbs_content_size,
+                     .buffer_content_size = tbs_content_size },
+            .signature = { .buffer = signature_buffer,
+                           .buffer_size = signature_content_size,
+                           .buffer_content_size = signature_content_size },
+          };
+
+          result = se.Verify(args) ? 0 : -EPERM;
+        }
+
+      if (result == 0)
+        {
+          printf("Signature verified successfully\n");
+        }
+    }
+  else if (settings->operation == KEYSTORE_SIGN_CSR)
+    {
+      char csr_pem_buf[DEFAULT_BUFFER_SIZE];
+      size_t csr_pem_buf_content_size
+          = readFromFile("enter csr(pem)", settings->input_filename,
+                         csr_pem_buf, sizeof(csr_pem_buf));
+
+      csr_pem_buf_content_size = addZeroTerminationCharacter(
+          csr_pem_buf, csr_pem_buf_content_size, sizeof(csr_pem_buf));
+
+      auto certificate = Controlse::CCertificate(
+          se, reinterpret_cast<uint8_t *>(csr_pem_buf),
+          csr_pem_buf_content_size, settings->key_id);
+
+      auto crt_pem = certificate.GetPem();
+      if (crt_pem)
+        {
+          puts(crt_pem);
+          delete[] crt_pem;
+        }
+      else
+        {
+          result = -EPERM;
+        }
+    }
+  else if (settings->operation == KEYSTORE_VERIFY_CERTIFICATE)
+    {
+      char pem_buf[DEFAULT_BUFFER_SIZE];
+      size_t pem_content_size
+          = readFromFile("enter crt(pem)", settings->input_filename, pem_buf,
+                         sizeof(pem_buf));
+
+      pem_content_size = addZeroTerminationCharacter(pem_buf, pem_content_size,
+                                                     sizeof(pem_buf));
+
+      auto certificate = Controlse::CCertificate(
+          reinterpret_cast<uint8_t *>(pem_buf), pem_content_size);
+
+      result = certificate.VerifyAgainst(se, settings->key_id) ? 0 : -EPERM;
+
+      if (result == 0)
+        {
+          printf("Signature verified successfully\n");
+        }
+    }
+
+  return result;
+}
+
+//***************************************************************************
+// Public Functions
+//**************************************************************************
+
+int main(int argc, FAR char *argv[])
+{
+  struct SSettings settings = DEFAULT_SETTINGS;
+  int result = parseArguments(argc, argv, &settings);
+
+  if ((result == 0) && (!settings.skip_process))
+    {
+      int fd = open(settings.se05x_dev_filename, O_RDONLY);
+      if (fd == -1)
+        {
+          result = -ENODEV;
+        }
+      else
+        {
+          result = process(fd, &settings);
+          close(fd);
+        }
+    }
+
+  if (result != 0)
+    {
+      fprintf(stderr, "err %i: %s\n", -result, strerror(-result));
+    }
+
+  if (settings.show_stack_used)
+    {
+#ifdef CONFIG_STACK_COLORATION
+      FAR struct tcb_s *tcb;
+      tcb = nxsched_get_tcb(getpid());
+      fprintf(stderr, "\nStack used: %zu / %zu\n", up_check_tcbstack(tcb),
+              tcb->adj_stack_size);
+#else
+      fprintf(stderr, "\nStack used: unknown"
+                      " (STACK_COLORATION must be enabled)\n");
+#endif
+    }
+
+  return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/crypto/controlse/cpublic_key.cxx b/crypto/controlse/cpublic_key.cxx
new file mode 100644
index 000000000..10a7aad91
--- /dev/null
+++ b/crypto/controlse/cpublic_key.cxx
@@ -0,0 +1,243 @@
+//***************************************************************************
+// apps/crypto/controlse/cpublic_key.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include "crypto/controlse/cpublic_key.hxx"
+#include "crypto/controlse/isecure_element.hxx"
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <errno.h>
+#include <mbedtls/pk.h>
+#include <string.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CPublicKey::CPublicKey(const ISecureElement &se, uint32_t keystore_id)
+{
+  (void)LoadFromSecureElement(se, keystore_id);
+}
+
+CPublicKey::CPublicKey(const char *pem)
+{
+  uint8_t key_buf[300];
+  m_key = nullptr;
+  if (0
+      == convert_public_key_pem_to_raw(key_buf, sizeof(key_buf), &m_size, pem))
+    {
+      m_key = new uint8_t[m_size];
+      memcpy(m_key, key_buf, m_size);
+    }
+}
+
+CPublicKey::CPublicKey(const uint8_t *buffer, size_t buffer_size)
+    : m_key(new uint8_t[buffer_size]), m_size(buffer_size)
+{
+  memcpy(m_key, buffer, m_size);
+}
+
+CPublicKey::CPublicKey(const CPublicKey &p1) : CPublicKey(p1.m_key, p1.m_size)
+{
+}
+
+CPublicKey::~CPublicKey() { Unload(); }
+
+CPublicKey &CPublicKey::operator=(const CPublicKey &other)
+{
+  if (this != &other)
+    {
+      auto new_key = new uint8_t[other.m_size];
+      memcpy(new_key, other.m_key, other.m_size);
+
+      delete[] m_key;
+
+      m_key = new_key;
+      m_size = other.m_size;
+    }
+  return *this;
+}
+
+void CPublicKey::Unload()
+{
+  if (IsLoaded())
+    {
+      delete[] m_key;
+      m_key = NULL;
+      m_size = 0;
+    }
+}
+
+bool CPublicKey::IsLoaded() const { return m_key != NULL; }
+
+bool CPublicKey::StoreOnSecureElement(const ISecureElement &se,
+                                      uint32_t keystore_id) const
+{
+  if (!IsLoaded())
+    {
+      return false;
+    }
+
+  struct se05x_key_transmission_s args = {
+    .entry = { .id = keystore_id, .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256 },
+    .content
+    = { .buffer = m_key, .buffer_size = m_size, .buffer_content_size = m_size }
+  };
+  return se.SetKey(args);
+}
+
+bool CPublicKey::LoadFromSecureElement(const ISecureElement &se,
+                                       uint32_t keystore_id)
+{
+  Unload();
+
+  m_size = 100;
+  m_key = new uint8_t[m_size];
+  struct se05x_key_transmission_s args = {
+    .entry = { .id = keystore_id, .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256 },
+    .content
+    = { .buffer = m_key, .buffer_size = m_size, .buffer_content_size = m_size }
+  };
+
+  bool result = se.GetKey(args);
+
+  m_size = args.content.buffer_content_size;
+  if (!result)
+    {
+      Unload();
+    }
+
+  return result;
+}
+
+bool CPublicKey::operator==(const CPublicKey &a) const
+{
+  if (this->m_size != a.m_size)
+    {
+      return false;
+    }
+  return 0 == memcmp(this->m_key, a.m_key, m_size);
+}
+
+bool CPublicKey::operator!=(const CPublicKey &a) const
+{
+  return !operator==(a);
+}
+
+size_t CPublicKey::GetRawSize() const { return m_size; }
+
+void CPublicKey::GetRaw(uint8_t *raw_buffer) const
+{
+  memcpy(raw_buffer, m_key, m_size);
+}
+
+char *CPublicKey::GetPem() const
+{
+  char pem_buf[500];
+  auto res
+      = convert_public_key_raw_to_pem(pem_buf, sizeof(pem_buf), m_key, m_size);
+  if (res < 0)
+    {
+      return nullptr;
+    }
+  auto pem_size = strlen(pem_buf);
+  auto pem = new char[pem_size + 1];
+  memcpy(pem, pem_buf, pem_size);
+  pem[pem_size] = 0;
+  return pem;
+}
+
+int CPublicKey::convert_public_key_raw_to_pem(char *pem_buf,
+                                              size_t pem_buf_size,
+                                              const uint8_t *key_buf,
+                                              size_t key_buf_size)
+{
+  mbedtls_pk_context key = { 0 };
+
+  mbedtls_pk_init(&key);
+  const mbedtls_pk_info_t *info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
+
+  int result = -1;
+  if (info != NULL)
+    {
+      result = mbedtls_pk_setup(&key, info);
+    }
+
+  mbedtls_ecp_keypair *keypair = (mbedtls_ecp_keypair *)key.pk_ctx;
+  if (result == 0)
+    {
+      result = mbedtls_ecp_group_load(&keypair->grp, MBEDTLS_ECP_DP_SECP256R1);
+    }
+
+  if (result == 0)
+    {
+      result = mbedtls_ecp_point_read_binary(&keypair->grp, &keypair->Q,
+                                             key_buf, key_buf_size);
+    }
+
+  if (result == 0)
+    {
+      result = mbedtls_pk_write_pubkey_pem(&key, (uint8_t *)pem_buf,
+                                           pem_buf_size);
+    }
+
+  mbedtls_pk_free(&key);
+  return result < 0 ? -EINVAL : 0;
+}
+
+int CPublicKey::convert_public_key_pem_to_raw(uint8_t *key_buf,
+                                              size_t key_buf_size,
+                                              size_t *key_size,
+                                              const char *pem_buf)
+{
+  int result = -1;
+  mbedtls_pk_context key = { 0 };
+
+  mbedtls_pk_init(&key);
+
+  result = mbedtls_pk_parse_public_key(&key, (uint8_t *)pem_buf,
+                                       strlen(pem_buf) + 1);
+
+  if (result == 0)
+    {
+      result = mbedtls_pk_can_do(&key, MBEDTLS_PK_ECKEY) == 1 ? 0 : -1;
+    }
+
+  if (result == 0)
+    {
+      mbedtls_ecp_keypair *keypair = (mbedtls_ecp_keypair *)key.pk_ctx;
+      result = mbedtls_ecp_point_write_binary(&keypair->grp, &keypair->Q,
+                                              MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                              key_size, key_buf, key_buf_size);
+    }
+
+  mbedtls_pk_free(&key);
+  return result < 0 ? -EINVAL : 0;
+}
+
+} // namespace Controlse
diff --git a/crypto/controlse/csan_builder.cxx b/crypto/controlse/csan_builder.cxx
new file mode 100644
index 000000000..60a9040ae
--- /dev/null
+++ b/crypto/controlse/csan_builder.cxx
@@ -0,0 +1,124 @@
+//***************************************************************************
+// apps/crypto/controlse/csan_builder.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/csan_builder.hxx"
+#include "mbedtls/asn1write.h"
+#include <cstring>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CSanBuilder::~CSanBuilder()
+{
+  while (entry != nullptr)
+    {
+      delete[] entry->p;
+      auto next_entry = entry->next;
+      delete entry;
+      entry = next_entry;
+    }
+}
+
+CSanBuilder *CSanBuilder::AddSan(uint8_t type, const char *value,
+                                 size_t value_size)
+{
+  auto old_entry = entry;
+  entry = new List();
+  if (entry)
+    {
+      entry->type = type;
+      entry->p = new char[value_size];
+      if (entry->p)
+        {
+          memcpy(entry->p, value, value_size);
+          entry->size = value_size;
+          entry->next = old_entry;
+          total_size += value_size;
+          total_size += 2;
+        }
+      else
+        {
+          delete entry;
+        }
+    }
+  return this;
+}
+
+//*
+// result: pointer to dynamically allocated san (to be deleted with delete[])
+// or error when size == 0
+///
+size_t CSanBuilder::Build(uint8_t **san)
+{
+  if (!entry)
+    {
+      return 0;
+    }
+
+  const size_t reservation_for_additional_length_bytes = 8;
+  const size_t buffer_size
+      = total_size + reservation_for_additional_length_bytes;
+  auto *buffer = new uint8_t[buffer_size];
+  auto current = entry;
+  const unsigned char *start = buffer;
+  unsigned char *p = buffer + buffer_size;
+  int ret = 0;
+  size_t len = 0;
+  while (current)
+    {
+      ret = mbedtls_asn1_write_tagged_string(&p, start, current->type,
+                                             current->p, current->size);
+      current = current->next;
+    }
+
+  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, start, total_size));
+  MBEDTLS_ASN1_CHK_ADD(
+      len, mbedtls_asn1_write_tag(
+               &p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+  *san = new uint8_t[total_size + len];
+  memcpy(*san, p, total_size + len);
+  delete[] buffer;
+  return total_size + len;
+}
+
+uint32_t CSanBuilder::GetNumberOfSan()
+{
+  auto e = entry;
+  uint32_t amount = 0;
+  while (e != nullptr)
+    {
+      e = e->next;
+      amount++;
+    }
+  return amount;
+}
+
+}
diff --git a/crypto/controlse/csecure_element.cxx b/crypto/controlse/csecure_element.cxx
new file mode 100644
index 000000000..e6c11d894
--- /dev/null
+++ b/crypto/controlse/csecure_element.cxx
@@ -0,0 +1,189 @@
+//***************************************************************************
+// apps/crypto/controlse/csecure_element.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/csecure_element.hxx"
+
+#include "crypto/controlse/ccertificate.hxx"
+#include "crypto/controlse/cpublic_key.hxx"
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+extern "C"
+{
+#include <nuttx/crypto/se05x.h>
+}
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CSecureElement::CSecureElement(const char *se05x_device)
+    : se05x_fd(open(se05x_device, O_RDONLY)), close_device_at_destructor(true)
+{
+}
+
+CSecureElement::CSecureElement(int fd)
+    : se05x_fd(fd), close_device_at_destructor(false)
+{
+}
+
+CSecureElement::~CSecureElement()
+{
+  if ((se05x_fd >= 0) && close_device_at_destructor)
+    {
+      close(se05x_fd);
+    }
+}
+
+bool CSecureElement::IsReady() const { return se05x_fd >= 0; }
+
+bool CSecureElement::GenerateKey(struct se05x_generate_keypair_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_GENERATE_KEYPAIR, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::SetKey(struct se05x_key_transmission_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_SET_KEY, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::GetKey(struct se05x_key_transmission_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_GET_KEY, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::DeleteKey(uint32_t id) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_DELETE_KEY, id);
+    }
+  return result;
+}
+
+bool CSecureElement::SetData(struct se05x_key_transmission_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_SET_DATA, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::GetData(struct se05x_key_transmission_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_GET_DATA, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::CreateSignature(struct se05x_signature_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_CREATE_SIGNATURE, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::Verify(struct se05x_signature_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_VERIFY_SIGNATURE, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::DeriveSymmetricalKey(
+    struct se05x_derive_key_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_DERIVE_SYMM_KEY, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::GetUid(struct se05x_uid_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_GET_UID, &args);
+    }
+  return result;
+}
+
+bool CSecureElement::GetInfo(struct se05x_info_s &args) const
+{
+  bool result = false;
+  if (se05x_fd >= 0)
+    {
+      result = 0 == ioctl(se05x_fd, SEIOC_GET_INFO, &args);
+    }
+  return result;
+}
+
+CCertificate *CSecureElement::GetCertificate(uint32_t keystore_id)
+{
+  return new CCertificate(*this, keystore_id);
+}
+
+CPublicKey *CSecureElement::GetPublicKey(uint32_t keystore_id)
+{
+  return new CPublicKey(*this, keystore_id);
+}
+
+} // namespace Controlse
diff --git a/crypto/controlse/cserial_number.cxx b/crypto/controlse/cserial_number.cxx
new file mode 100644
index 000000000..517d1b229
--- /dev/null
+++ b/crypto/controlse/cserial_number.cxx
@@ -0,0 +1,94 @@
+//***************************************************************************
+// apps/crypto/controlse/cserial_number.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/cserial_number.hxx"
+#include "crypto/controlse/isecure_element.hxx"
+#include <string.h>
+
+namespace Controlse
+{
+constexpr size_t CSerialNumber::SERIAL_NUMBER_SIZE;
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CSerialNumber::CSerialNumber(const ISecureElement &se, uint32_t keystore_id)
+{
+  is_loaded = LoadFromSecureElement(se, keystore_id);
+}
+
+CSerialNumber::CSerialNumber(uint8_t const *serial_number_byte_array)
+{
+  memcpy(serial_number, serial_number_byte_array, SERIAL_NUMBER_SIZE);
+  is_loaded = true;
+}
+
+bool CSerialNumber::operator==(CSerialNumber &a) const
+{
+  return 0 == (memcmp(a.serial_number, serial_number, SERIAL_NUMBER_SIZE));
+}
+
+bool CSerialNumber::operator!=(CSerialNumber &a) const
+{
+  return !operator==(a);
+}
+
+bool CSerialNumber::operator<(const CSerialNumber &a) const
+{
+  return 0 < (memcmp(a.serial_number, serial_number, SERIAL_NUMBER_SIZE));
+}
+
+bool CSerialNumber::IsLoaded() const { return is_loaded; }
+
+bool CSerialNumber::GetSerialNumber(
+    uint8_t serial_number_destination[SERIAL_NUMBER_SIZE]) const
+{
+  if (!is_loaded)
+    {
+      return false;
+    }
+
+  memcpy(serial_number_destination, serial_number, SERIAL_NUMBER_SIZE);
+  return true;
+}
+
+bool CSerialNumber::StoreOnSecureElement(const ISecureElement &se,
+                                         uint32_t keystore_id) const
+{
+  return false;
+}
+
+bool CSerialNumber::LoadFromSecureElement(const ISecureElement &se,
+                                          uint32_t keystore_id)
+{
+  struct se05x_key_transmission_s args
+      = { .entry = { .id = keystore_id },
+          .content
+          = { .buffer = serial_number, .buffer_size = SERIAL_NUMBER_SIZE } };
+  return se.GetData(args);
+}
+} // namespace Controlse
diff --git a/crypto/controlse/cstring.cxx b/crypto/controlse/cstring.cxx
new file mode 100644
index 000000000..ff7637005
--- /dev/null
+++ b/crypto/controlse/cstring.cxx
@@ -0,0 +1,141 @@
+//***************************************************************************
+// apps/crypto/controlse/cstring.cxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/cstring.hxx"
+#include "crypto/controlse/csecure_element.hxx"
+#include <cstring>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class Method Implementations
+//***************************************************************************
+
+CString::CString(const ISecureElement &se, uint32_t keystore_id)
+{
+  (void)LoadFromSecureElement(se, keystore_id);
+}
+
+CString::CString(char *string, size_t size) : m_size(size)
+{
+  m_string = new char[m_size];
+  memcpy(m_string, string, m_size);
+}
+
+CString::CString(const CString &p1) : CString(p1.m_string, p1.m_size) {}
+
+CString::~CString()
+{
+  if (m_string != nullptr)
+    {
+      delete[] m_string;
+      m_size = 0;
+    }
+}
+
+CString &CString::operator=(const CString &other)
+{
+  if (this != &other)
+    {
+      auto new_string = new char[other.m_size];
+      memcpy(new_string, other.m_string, other.m_size);
+
+      delete[] m_string;
+
+      m_string = new_string;
+      m_size = other.m_size;
+    }
+  return *this;
+}
+
+bool CString::operator==(CString &a) const
+{
+  if (a.m_size != m_size)
+    {
+      return false;
+    }
+  return 0 == (memcmp(a.m_string, m_string, m_size));
+}
+
+bool CString::operator!=(CString &a) const { return !operator==(a); }
+
+char *CString::c_str(void) const
+{
+  char *c_str = nullptr;
+  if (IsLoaded() && (m_size > 0))
+    {
+      bool add_termination_character = false;
+      if (m_string[m_size - 1] != 0)
+        {
+          add_termination_character = true;
+        }
+      c_str = new char[m_size + (add_termination_character ? 1 : 0)];
+      memcpy(c_str, m_string, m_size);
+      if (add_termination_character)
+        {
+          c_str[m_size] = 0;
+        }
+    }
+  return c_str;
+}
+
+bool CString::IsLoaded() const { return m_string != nullptr; }
+
+bool CString::StoreOnSecureElement(const ISecureElement &se,
+                                   uint32_t keystore_id) const
+{
+  auto result = false;
+  if (IsLoaded())
+    {
+      struct se05x_key_transmission_s args
+          = { .entry = { .id = keystore_id },
+              .content = { .buffer = reinterpret_cast<uint8_t *>(m_string),
+                           .buffer_size = m_size } };
+      result = se.SetData(args);
+    }
+  return result;
+}
+
+bool CString::LoadFromSecureElement(const ISecureElement &se,
+                                    uint32_t keystore_id)
+{
+  uint8_t buffer[1000];
+  struct se05x_key_transmission_s args
+      = { .entry = { .id = keystore_id },
+          .content = { .buffer = buffer, .buffer_size = sizeof(buffer) } };
+  auto result = se.GetData(args);
+
+  if (result)
+    {
+      m_size = args.content.buffer_content_size;
+      m_string = new char[m_size + 1];
+      memcpy(m_string, buffer, m_size);
+      m_string[m_size] = 0;
+    }
+  return result;
+}
+} // namespace Controlse
diff --git a/crypto/controlse/mbedtls_extension.c b/crypto/controlse/mbedtls_extension.c
deleted file mode 100644
index 3ec58ae74..000000000
--- a/crypto/controlse/mbedtls_extension.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/****************************************************************************
- * apps/crypto/controlse/mbedtls_extension.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you 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.
- *
- ****************************************************************************/
-
-/* Copyright The Mbed TLS Contributors
- * SPDX-License-Identifier: Apache-2.0
- *
- * The source code in this file is based on
- * mbedtls_x509write_crt_der() method from x509write_crt.c in Mbed TLS
- */
-
-/* Copyright 2023 NXP */
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-#include <mbedtls/asn1write.h>
-#include <mbedtls/error.h>
-#include <mbedtls/oid.h>
-#include <mbedtls/x509_crt.h>
-#include <nuttx/crypto/se05x.h>
-#include <sys/ioctl.h>
-#include <string.h>
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static int x509_write_time(FAR unsigned char **p, FAR unsigned char *start,
-                           FAR const char *t, size_t size)
-{
-  int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-  size_t len = 0;
-
-  /* write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */
-
-  if (t[0] == '2' && t[1] == '0' && t[2] < '5')
-    {
-      MBEDTLS_ASN1_CHK_ADD(
-          len, mbedtls_asn1_write_raw_buffer(
-                   p, start, (FAR const unsigned char *)t + 2, size - 2));
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-      MBEDTLS_ASN1_CHK_ADD(
-          len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_UTC_TIME));
-    }
-  else
-    {
-      MBEDTLS_ASN1_CHK_ADD(len,
-                           mbedtls_asn1_write_raw_buffer(
-                             p, start, (FAR const unsigned char *)t, size));
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(
-                                  p, start, MBEDTLS_ASN1_GENERALIZED_TIME));
-    }
-
-  return ((int)len);
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-int mbedtls_x509write_crt_der_se05x(FAR mbedtls_x509write_cert *ctx,
-                                    FAR unsigned char *buf, size_t size,
-                                    int se05x_fd, uint32_t private_key_id)
-{
-  int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-  FAR const char *sig_oid;
-  size_t sig_oid_len = 0;
-  FAR unsigned char *c;
-  FAR unsigned char *c2;
-  unsigned char hash[64];
-  unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
-  size_t sub_len = 0;
-  size_t pub_len = 0;
-  size_t sig_and_oid_len = 0;
-  size_t sig_len;
-  size_t len = 0;
-  mbedtls_pk_type_t pk_alg;
-
-  /* Prepare data to be signed at the end of the target buffer */
-
-  c = buf + size;
-
-  /* Signature algorithm needed in TBS, and later for actual signature */
-
-  /* There's no direct way of extracting a signature algorithm
-   * (represented as an element of mbedtls_pk_type_t) from a PK instance.
-   */
-
-  if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA))
-    {
-      pk_alg = MBEDTLS_PK_RSA;
-    }
-  else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA))
-    {
-      pk_alg = MBEDTLS_PK_ECDSA;
-    }
-  else
-    {
-      return (MBEDTLS_ERR_X509_INVALID_ALG);
-    }
-
-  if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid,
-                                            &sig_oid_len)) != 0)
-    {
-      return (ret);
-    }
-
-  /* Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension */
-
-  /* Only for v3 */
-
-  if (ctx->version == MBEDTLS_X509_CRT_VERSION_3)
-    {
-      MBEDTLS_ASN1_CHK_ADD(
-          len, mbedtls_x509_write_extensions(&c, buf, ctx->extensions));
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-      MBEDTLS_ASN1_CHK_ADD(len,
-                           mbedtls_asn1_write_tag(&c, buf,
-                                                  MBEDTLS_ASN1_CONSTRUCTED |
-                                                    MBEDTLS_ASN1_SEQUENCE));
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-      MBEDTLS_ASN1_CHK_ADD(
-          len, mbedtls_asn1_write_tag(&c, buf,
-                                      MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                          MBEDTLS_ASN1_CONSTRUCTED | 3));
-    }
-
-  /*  SubjectPublicKeyInfo  */
-
-  MBEDTLS_ASN1_CHK_ADD(
-      pub_len, mbedtls_pk_write_pubkey_der(ctx->subject_key, buf, c - buf));
-  c -= pub_len;
-  len += pub_len;
-
-  /*  Subject  ::=  Name  */
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject));
-
-  /*  Validity ::= SEQUENCE {
-   *       notBefore      Time,
-   *       notAfter       Time }
-   */
-
-  sub_len = 0;
-
-  MBEDTLS_ASN1_CHK_ADD(sub_len,
-                       x509_write_time(&c, buf, ctx->not_after,
-                                       MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
-
-  MBEDTLS_ASN1_CHK_ADD(sub_len,
-                       x509_write_time(&c, buf, ctx->not_before,
-                                       MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
-
-  len += sub_len;
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));
-  MBEDTLS_ASN1_CHK_ADD(
-      len, mbedtls_asn1_write_tag(
-               &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
-
-  /*  Issuer  ::=  Name  */
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->issuer));
-
-  /*  Signature   ::=  AlgorithmIdentifier  */
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(
-                                &c, buf, sig_oid, strlen(sig_oid), 0));
-
-  /*  Serial   ::=  INTEGER
-   *
-   * Written data is:
-   * - "ctx->serial_len" bytes for the raw serial buffer
-   *   - if MSb of "serial" is 1, then prepend an extra 0x00 byte
-   * - 1 byte for the length
-   * - 1 byte for the TAG
-   */
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf,
-                                            ctx->serial, ctx->serial_len));
-  if (*c & 0x80)
-    {
-      if (c - buf < 1)
-        {
-          return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
-        }
-
-      *(--c) = 0x0;
-      len++;
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
-                                                       ctx->serial_len + 1));
-    }
-  else
-    {
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
-                                                       ctx->serial_len));
-    }
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
-                                                   MBEDTLS_ASN1_INTEGER));
-
-  /*  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }  */
-
-  /* Can be omitted for v1 */
-
-  if (ctx->version != MBEDTLS_X509_CRT_VERSION_1)
-    {
-      sub_len = 0;
-      MBEDTLS_ASN1_CHK_ADD(sub_len,
-                           mbedtls_asn1_write_int(&c, buf, ctx->version));
-      len += sub_len;
-      MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));
-      MBEDTLS_ASN1_CHK_ADD(
-          len, mbedtls_asn1_write_tag(&c, buf,
-                                      MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                          MBEDTLS_ASN1_CONSTRUCTED | 0));
-    }
-
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-  MBEDTLS_ASN1_CHK_ADD(
-      len, mbedtls_asn1_write_tag(
-               &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
-
-  /* Make signature
-   */
-
-  /* Compute hash of CRT. */
-
-  if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len,
-                        hash)) != 0)
-    {
-      return (ret);
-    }
-
-    {
-      struct se05x_signature_s args = {
-          .key_id = private_key_id,
-          .algorithm = SE05X_ALGORITHM_SHA256,
-          .tbs = {
-            .buffer = hash,
-            .buffer_size = 32,
-            .buffer_content_size = 32
-          },
-          .signature = {.buffer = sig, .buffer_size = sizeof(sig)},
-      };
-
-      ret = ioctl(se05x_fd, SEIOC_CREATE_SIGNATURE, &args);
-      if (ret != 0)
-        {
-          return ret;
-        }
-
-      sig_len = args.signature.buffer_content_size;
-    }
-
-  /* Move CRT to the front of the buffer to have space
-   * for the signature.
-   */
-
-  memmove(buf, c, len);
-  c = buf + len;
-
-  /* Add signature at the end of the buffer,
-   * making sure that it doesn't underflow
-   * into the CRT buffer.
-   */
-
-  c2 = buf + size;
-  MBEDTLS_ASN1_CHK_ADD(
-      sig_and_oid_len,
-      mbedtls_x509_write_sig(&c2, c, sig_oid, sig_oid_len, sig, sig_len));
-
-  /* Memory layout after this step:
-   *
-   * buf       c=buf+len                c2            buf+size
-   * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
-   */
-
-  /* Move raw CRT to just before the signature. */
-
-  c = c2 - len;
-  memmove(c, buf, len);
-
-  len += sig_and_oid_len;
-  MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-  MBEDTLS_ASN1_CHK_ADD(
-      len, mbedtls_asn1_write_tag(
-               &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
-
-  return ((int)len);
-}
diff --git a/crypto/controlse/mbedtls_extension.h b/crypto/controlse/mbedtls_extension.h
deleted file mode 100644
index 74a1c0349..000000000
--- a/crypto/controlse/mbedtls_extension.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
- * apps/crypto/controlse/mbedtls_extension.h
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you 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.
- *
- ****************************************************************************/
-
-/* Copyright 2023 NXP */
-
-#ifndef __INCLUDE_APPS_CRYPTO_CONTROLSE_MBEDTLS_EXTENSION_H_
-#define __INCLUDE_APPS_CRYPTO_CONTROLSE_MBEDTLS_EXTENSION_H_
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <mbedtls/x509_crt.h>
-
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-int mbedtls_x509write_crt_der_se05x(mbedtls_x509write_cert *ctx,
-                                    unsigned char *buf, size_t size,
-                                    int se05x_fd, uint32_t private_key_id);
-
-#endif /* __INCLUDE_APPS_CRYPTO_CONTROLSE_MBEDTLS_EXTENSION_H_ */
diff --git a/crypto/controlse/x509_utils.c b/crypto/controlse/x509_utils.c
deleted file mode 100644
index 873b54ec6..000000000
--- a/crypto/controlse/x509_utils.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/****************************************************************************
- * apps/crypto/controlse/x509_utils.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you 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.
- *
- ****************************************************************************/
-
-/* Copyright 2023 NXP */
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <errno.h>
-#include <string.h>
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/ecp.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/pem.h"
-#include "mbedtls/pk.h"
-#include "mbedtls/x509_crt.h"
-#include "mbedtls/x509_csr.h"
-#include "mbedtls_extension.h"
-#include <time.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-#define SECONDS_IN_DAY (60 * 60 * 24)
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-static const char certificate_header[] = "-----BEGIN CERTIFICATE-----\n";
-static const char certificate_footer[] = "-----END CERTIFICATE-----\n";
-
-static const char certificate_request_header[] =
-    "-----BEGIN CERTIFICATE REQUEST-----\n";
-static const char certificate_request_footer[] =
-    "-----END CERTIFICATE REQUEST-----\n";
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static int convert_der_certificate_to_pem(FAR char *pem_buf,
-                                          size_t pem_buf_size,
-                                          FAR size_t *pem_content_size,
-                                          FAR uint8_t *der_buf,
-                                          size_t der_buf_size)
-{
-  int result;
-
-    {
-      mbedtls_x509_crt crt;
-      mbedtls_x509_crt_init(&crt);
-      result = mbedtls_x509_crt_parse(&crt, der_buf, der_buf_size);
-      mbedtls_x509_crt_free(&crt);
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_pem_write_buffer(
-          certificate_header, certificate_footer, der_buf, der_buf_size,
-          (FAR uint8_t *)pem_buf, pem_buf_size, pem_content_size);
-    }
-
-  return result;
-}
-
-static int convert_der_csr_to_pem(FAR char *pem_buf, size_t pem_buf_size,
-                                  FAR size_t *pem_content_size,
-                                  FAR uint8_t *der_buf, size_t der_buf_size)
-{
-  int result;
-
-    {
-      mbedtls_x509_csr csr;
-      mbedtls_x509_csr_init(&csr);
-      result =
-          mbedtls_x509_csr_parse(&csr, (FAR uint8_t *)der_buf, der_buf_size);
-      mbedtls_x509_csr_free(&csr);
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_pem_write_buffer(certificate_request_header,
-                                        certificate_request_footer, der_buf,
-                                        der_buf_size, (FAR uint8_t *)pem_buf,
-                                        pem_buf_size, pem_content_size);
-    }
-
-  return result;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-int convert_public_key_raw_to_pem(FAR char *pem_buf, size_t pem_buf_size,
-                                  FAR uint8_t *key_buf, size_t key_buf_size)
-{
-  mbedtls_pk_context key =
-    {
-      0
-    };
-
-  mbedtls_pk_init(&key);
-  FAR const mbedtls_pk_info_t *info =
-      mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
-
-  int result = -1;
-  if (info != NULL)
-    {
-      result = mbedtls_pk_setup(&key, info);
-    }
-
-  FAR mbedtls_ecp_keypair *keypair = (mbedtls_ecp_keypair *)key.pk_ctx;
-  if (result == 0)
-    {
-      result =
-          mbedtls_ecp_group_load(&keypair->grp, MBEDTLS_ECP_DP_SECP256R1);
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_ecp_point_read_binary(&keypair->grp, &keypair->Q,
-                                             key_buf, key_buf_size);
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_pk_write_pubkey_pem(&key, (FAR uint8_t *)pem_buf,
-                                           pem_buf_size);
-    }
-
-  mbedtls_pk_free(&key);
-  return result < 0 ? -EINVAL : 0;
-}
-
-int convert_public_key_pem_to_raw(FAR uint8_t *key_buf, size_t key_buf_size,
-                                  FAR size_t *key_size, FAR char *pem_buf)
-{
-  int result = -1;
-  mbedtls_pk_context key =
-    {
-      0
-    };
-
-  mbedtls_pk_init(&key);
-
-  result = mbedtls_pk_parse_public_key(&key, (FAR uint8_t *)pem_buf,
-                                       strlen(pem_buf) + 1);
-
-  if (result == 0)
-    {
-      result = mbedtls_pk_can_do(&key, MBEDTLS_PK_ECKEY) == 1 ? 0 : -1;
-    }
-
-  if (result == 0)
-    {
-      FAR mbedtls_ecp_keypair *keypair = (mbedtls_ecp_keypair *)key.pk_ctx;
-      result = mbedtls_ecp_point_write_binary(
-          &keypair->grp, &keypair->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, key_size,
-          key_buf, key_buf_size);
-    }
-
-  mbedtls_pk_free(&key);
-  return result < 0 ? -EINVAL : 0;
-}
-
-int convert_pem_certificate_or_csr_to_der(FAR uint8_t *der_buf,
-                                          size_t der_buf_size,
-                                          FAR size_t *der_content_size,
-                                          FAR char *pem_buf,
-                                          size_t pem_buf_size)
-{
-  int result;
-
-    {
-      mbedtls_x509_crt crt;
-      mbedtls_x509_crt_init(&crt);
-      result =
-          mbedtls_x509_crt_parse(&crt, (FAR uint8_t *)pem_buf, pem_buf_size);
-      if ((result == 0) && (der_buf_size < crt.raw.len))
-        {
-          result = -EINVAL;
-        }
-
-      if (result == 0)
-        {
-          memcpy(der_buf, crt.raw.p, crt.raw.len);
-          *der_content_size = crt.raw.len;
-        }
-
-      mbedtls_x509_crt_free(&crt);
-    }
-
-  /* if bad input data then try parsing CSR */
-
-  if (result != 0)
-    {
-      mbedtls_x509_csr csr;
-      mbedtls_x509_csr_init(&csr);
-      result =
-          mbedtls_x509_csr_parse(&csr, (FAR uint8_t *)pem_buf, pem_buf_size);
-      if ((result == 0) && (der_buf_size < csr.raw.len))
-        {
-          result = -EINVAL;
-        }
-
-      if (result == 0)
-        {
-          memcpy(der_buf, csr.raw.p, csr.raw.len);
-          *der_content_size = csr.raw.len;
-        }
-
-      mbedtls_x509_csr_free(&csr);
-    }
-
-  return result;
-}
-
-int convert_der_certificate_or_csr_to_pem(FAR char *pem_buf,
-                                          size_t pem_buf_size,
-                                          FAR size_t *pem_content_size,
-                                          FAR uint8_t *der_buf,
-                                          size_t der_buf_size)
-{
-  int result = convert_der_certificate_to_pem(
-      pem_buf, pem_buf_size, pem_content_size, der_buf, der_buf_size);
-
-  if (result != 0)
-    {
-      result = convert_der_csr_to_pem(pem_buf, pem_buf_size,
-                                      pem_content_size,
-                                      der_buf, der_buf_size);
-    }
-
-  return result;
-}
-
-int sign_csr(int se05x_fd, uint32_t private_key_id, FAR char *crt_pem_buf,
-             size_t crt_pem_buf_size, FAR char *csr_pem_buf,
-             size_t csr_pem_buf_content_size)
-{
-  mbedtls_x509_csr csr;
-  mbedtls_x509_csr_init(&csr);
-  int result = mbedtls_x509_csr_parse(&csr, (FAR uint8_t *)csr_pem_buf,
-                                      csr_pem_buf_content_size);
-
-  mbedtls_x509write_cert crt;
-  mbedtls_x509write_crt_init(&crt);
-  char subject_name[200];
-  if (result == 0)
-    {
-      mbedtls_x509write_crt_set_version(&crt, MBEDTLS_X509_CRT_VERSION_3);
-      result = mbedtls_x509_dn_gets(subject_name, sizeof(subject_name),
-                                    &csr.subject);
-    }
-
-  mbedtls_pk_context private_key;
-  mbedtls_pk_init(&private_key);
-  if (result >= 0)
-    {
-      mbedtls_x509write_crt_set_subject_key(&crt, &csr.pk);
-      result = mbedtls_pk_setup(
-          &private_key,
-          mbedtls_pk_info_from_type((mbedtls_pk_type_t)MBEDTLS_PK_ECDSA));
-    }
-
-  if (result == 0)
-    {
-      mbedtls_x509write_crt_set_issuer_key(&crt, &private_key);
-      result = mbedtls_x509write_crt_set_subject_name(&crt, subject_name);
-    }
-
-  if (result == 0)
-    {
-      result =
-          mbedtls_x509write_crt_set_issuer_name(&crt, "CN=CA,O=NXP,C=NL");
-    }
-
-  mbedtls_mpi serial;
-  mbedtls_mpi_init(&serial);
-  if (result == 0)
-    {
-      mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
-      result = mbedtls_mpi_read_string(&serial, 10, "1");
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_x509write_crt_set_serial(&crt, &serial);
-    }
-
-  if (result == 0)
-    {
-      time_t rawtime;
-      struct tm tm_info;
-      char from_datetime[20];
-      char to_datetime[20];
-      time(&rawtime);
-      strftime(from_datetime, sizeof(from_datetime), "%Y%m%d%H%M%S",
-               gmtime_r(&rawtime, &tm_info));
-      rawtime += SECONDS_IN_DAY;
-      strftime(to_datetime, sizeof(to_datetime), "%Y%m%d%H%M%S",
-               gmtime_r(&rawtime, &tm_info));
-      result = mbedtls_x509write_crt_set_validity(&crt, from_datetime,
-                                                  to_datetime);
-    }
-
-  if (result == 0)
-    {
-      result = mbedtls_x509write_crt_der_se05x(
-          &crt, (FAR uint8_t *)crt_pem_buf, crt_pem_buf_size, se05x_fd,
-          private_key_id);
-    }
-
-  if (result >= 0)
-    {
-      size_t olen;
-      result = mbedtls_pem_write_buffer(
-          certificate_header, certificate_footer,
-          (FAR uint8_t *)(crt_pem_buf + crt_pem_buf_size - result), result,
-          (FAR uint8_t *)crt_pem_buf, crt_pem_buf_size, &olen);
-    }
-
-  mbedtls_mpi_free(&serial);
-  mbedtls_pk_free(&private_key);
-  mbedtls_x509write_crt_free(&crt);
-  mbedtls_x509_csr_free(&csr);
-  return result;
-}
diff --git a/crypto/controlse/x509_utils.h b/crypto/controlse/x509_utils.h
deleted file mode 100644
index 872136271..000000000
--- a/crypto/controlse/x509_utils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
- * apps/crypto/controlse/x509_utils.h
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you 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.
- *
- ****************************************************************************/
-
-/* Copyright 2023 NXP */
-
-#ifndef __INCLUDE_APPS_CRYPTO_CONTROLSE_X509_UTILS_H_
-#define __INCLUDE_APPS_CRYPTO_CONTROLSE_X509_UTILS_H_
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <stdint.h>
-
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-int convert_public_key_raw_to_pem(FAR char *pem_buf, size_t pem_buf_size,
-                                  FAR uint8_t *key_buf, size_t key_buf_size);
-int convert_public_key_pem_to_raw(FAR uint8_t *key_buf, size_t key_buf_size,
-                                  FAR size_t *key_size, char *pem_buf);
-int convert_pem_certificate_or_csr_to_der(FAR uint8_t *der_buf,
-                                          size_t der_buf_size,
-                                          FAR size_t *der_content_size,
-                                          FAR char *pem_buf,
-                                          size_t pem_buf_size);
-int convert_der_certificate_or_csr_to_pem(FAR char *pem_buf,
-                                          size_t pem_buf_size,
-                                          FAR size_t *pem_content_size,
-                                          FAR uint8_t *der_buf,
-                                          size_t der_buf_size);
-int sign_csr(int se05x_fd, uint32_t private_key_id, FAR char *crt_pem_buf,
-             size_t crt_pem_buf_size, FAR char *csr_pem_buf,
-             size_t csr_pem_buf_content_size);
-
-#endif /* __INCLUDE_APPS_CRYPTO_CONTROLSE_X509_UTILS_H_ */
diff --git a/include/crypto/controlse/ccertificate.hxx b/include/crypto/controlse/ccertificate.hxx
new file mode 100644
index 000000000..72bc45ac7
--- /dev/null
+++ b/include/crypto/controlse/ccertificate.hxx
@@ -0,0 +1,122 @@
+//***************************************************************************
+// apps/include/crypto/controlse/ccertificate.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//***************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <mbedtls/x509_crt.h>
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+namespace Controlse
+{
+class ISecureElement;
+class CPublicKey;
+class CSerialNumber;
+
+class CCertificate : public ISecureElementObject
+{
+public:
+  CCertificate(const ISecureElement &se, uint32_t keystore_id);
+  CCertificate(const uint8_t *crt_der_or_pem, size_t crt_size);
+  CCertificate(const ISecureElement &se, const uint8_t *csr_der_or_pem,
+               size_t csr_size, uint32_t keystore_id);
+
+  // from_datetime and to_datetime need to have format: YYYYMMDDHHMMSSZ
+  CCertificate(const ISecureElement &se, const uint8_t *csr_der_or_pem,
+               size_t csr_size, uint32_t keystore_id,
+               const char *from_datetime, const char *to_datetime);
+  CCertificate(const CCertificate &) = delete;
+  CCertificate(CCertificate &&) = default;
+  ~CCertificate();
+
+  CCertificate &operator=(const CCertificate &other) = delete;
+
+  bool IsLoaded() const;
+  bool StoreOnSecureElement(const ISecureElement &se,
+                            uint32_t keystore_id) const;
+  bool LoadFromSecureElement(const ISecureElement &se, uint32_t keystore_id);
+  bool LoadFromDerOrPem(const uint8_t *crt_der_or_pem, size_t crt_size);
+  bool LoadFromCsrDerOrPem(const ISecureElement &se,
+                           const uint8_t *csr_der_or_pem, size_t csr_size,
+                           uint32_t keystore_id, const char *from_datetime,
+                           const char *to_datetime);
+
+  bool VerifyAgainst(const ISecureElement &se,
+                     uint32_t verify_against_id) const;
+
+  // Test time range is valid
+  // returns 0 if valid
+  //  -1 when expired
+  //  1 when not yet valid
+  int TestValidTimerange(time_t now) const;
+
+  // Get public key from certificate
+  // returns pointer to public key when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  CPublicKey *GetPublicKey() const;
+
+  // Get oid from certificate if available
+  // oid must be one of MBEDTLS_OID_AT* from mbedtls/oid.h
+  //
+  // returns zero terminated text string when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  char *GetOid(const char *oid) const;
+
+  // Get serial number from from certificate
+  // returns pointer to CSerialNumber when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  CSerialNumber *GetSerialNumber() const;
+
+  size_t GetNumberOfSubjectAlternativeNames() const;
+
+  // Get SAN from from certificate
+  // returns pointer to array when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  char *GetSubjectAlternativeName(int item) const;
+
+  // Get certificate in DER format
+  // returns size of the der array otherwise 0
+  // note: der must be deleted by caller when not NULL
+  size_t GetDer(uint8_t **der) const;
+
+  // Get certificate in PEM format
+  // returns pointer to pem string when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  char *GetPem() const;
+
+  bool ContainsSan(const char *name, size_t size) const;
+
+  static constexpr char TAG_ID_SIZE = 18;
+
+private:
+  bool is_loaded = false;
+
+  mbedtls_x509_crt crt;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/ccsr.hxx b/include/crypto/controlse/ccsr.hxx
new file mode 100644
index 000000000..672866050
--- /dev/null
+++ b/include/crypto/controlse/ccsr.hxx
@@ -0,0 +1,92 @@
+//***************************************************************************
+// apps/include/crypto/controlse/ccsr.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include "mbedtls/x509_csr.h"
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CCsr : public ISecureElementObject
+{
+public:
+  class CsrBuilder;
+  class CsrBuilder
+  {
+  public:
+    CsrBuilder(ISecureElement &se, const char *subject, uint32_t key_slot_id);
+    CsrBuilder(const CsrBuilder &) = delete;
+    CsrBuilder(CsrBuilder &&) = default;
+
+    CsrBuilder &operator=(const CsrBuilder &other) = delete;
+
+    CsrBuilder *AddExtension(const char *oid, size_t oid_size,
+                             const uint8_t *value, size_t value_size);
+
+    // result: pointer to dynamically allocated Csr (to be deleted) or nullptr
+    // if error
+    CCsr *Build();
+
+  private:
+    mbedtls_x509write_csr csr_w;
+    mbedtls_pk_context key;
+    bool ready;
+  };
+
+  CCsr(const ISecureElement &se, uint32_t keystore_id);
+  CCsr(const uint8_t *der_or_pem, size_t size);
+  CCsr(const CCsr &) = delete;
+  CCsr(CCsr &&) = default;
+  ~CCsr();
+
+  CCsr &operator=(const CCsr &other) = delete;
+
+  bool IsLoaded() const;
+  bool StoreOnSecureElement(const ISecureElement &se,
+                            uint32_t keystore_id) const;
+  bool LoadFromSecureElement(const ISecureElement &se, uint32_t keystore_id);
+
+  // Get CSR in DER format
+  // returns size of the der array otherwise 0
+  // note: der must be deleted by caller when not NULL
+  size_t GetDer(uint8_t **der) const;
+
+  // Get certificate in PEM format
+  // returns pointer to pem string when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  char *GetPem() const;
+
+private:
+  mbedtls_x509_csr csr;
+  bool is_loaded = false;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/chex_util.hxx b/include/crypto/controlse/chex_util.hxx
new file mode 100644
index 000000000..446518148
--- /dev/null
+++ b/include/crypto/controlse/chex_util.hxx
@@ -0,0 +1,62 @@
+//***************************************************************************
+// apps/include/crypto/controlse/chex_util.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include <cstddef>
+#include <cstdint>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CHexUtil
+{
+public:
+  static size_t GetByteArraySizeFromHexString(const char *hex_buffer);
+  static size_t GetByteArraySizeFromHexStringSize(size_t hex_buffer_size);
+  static size_t GetHexStringSizeFromByteArraySize(size_t byte_array_size);
+
+  // result contains allocated pointer to byte array (delete[] afterwards) if
+  // successfull otherwise nullptr
+  static uint8_t *ConvertHexStringToByteArray(const char *hex_buffer);
+
+  // result contains allocated pointer to byte array (delete[] afterwards) if
+  // successfull otherwise nullptr
+  static uint8_t *ConvertHexStringToByteArray(const char *hex_buffer,
+                                              size_t hex_buffer_size);
+
+  // result contains allocated pointer to hex string (delete[] afterwards) if
+  // successfull otherwise nullptr
+  static char *ByteArrayToHexString(const uint8_t bytearray[], size_t size);
+
+private:
+  static constexpr size_t AMOUNT_OF_HEXDIGITS_PER_BYTE = 2;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/cpublic_key.hxx b/include/crypto/controlse/cpublic_key.hxx
new file mode 100644
index 000000000..eed61ca15
--- /dev/null
+++ b/include/crypto/controlse/cpublic_key.hxx
@@ -0,0 +1,82 @@
+//***************************************************************************
+// apps/include/crypto/controlse/cpublic_key.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <stddef.h>
+
+struct mbedtls_x509_crt;
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class ISecureElement;
+
+class CPublicKey : public ISecureElementObject
+{
+public:
+  CPublicKey(const ISecureElement &se, uint32_t keystore_id);
+  CPublicKey(const uint8_t *buffer, size_t buffer_size);
+  CPublicKey(const char *pem);
+  CPublicKey(const CPublicKey &p1);
+  ~CPublicKey();
+
+  CPublicKey &operator=(const CPublicKey &other);
+
+  bool IsLoaded() const;
+  bool StoreOnSecureElement(const ISecureElement &se,
+                            uint32_t keystore_id) const;
+  bool LoadFromSecureElement(const ISecureElement &se, uint32_t keystore_id);
+  bool operator==(const CPublicKey &a) const;
+  bool operator!=(const CPublicKey &a) const;
+
+  size_t GetRawSize() const;
+  void GetRaw(uint8_t *raw_buffer) const;
+
+  // Get public key in PEM format
+  // returns pointer to pem string when successful otherwise NULL
+  // note: must be deleted by caller when not NULL
+  char *GetPem() const;
+
+private:
+  void Unload();
+  static int convert_public_key_raw_to_pem(char *pem_buf, size_t pem_buf_size,
+                                           const uint8_t *key_buf,
+                                           size_t key_buf_size);
+  static int convert_public_key_pem_to_raw(uint8_t *key_buf,
+                                           size_t key_buf_size,
+                                           size_t *key_size,
+                                           const char *pem_buf);
+
+  uint8_t *m_key = nullptr;
+  size_t m_size = 0;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/csan_builder.hxx b/include/crypto/controlse/csan_builder.hxx
new file mode 100644
index 000000000..c992e94c0
--- /dev/null
+++ b/include/crypto/controlse/csan_builder.hxx
@@ -0,0 +1,69 @@
+//***************************************************************************
+// apps/include/crypto/controlse/csan_builder.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CSanBuilder;
+class CSanBuilder
+{
+public:
+  CSanBuilder() = default;
+  CSanBuilder(const CSanBuilder &) = delete;
+  CSanBuilder(CSanBuilder &&) = default;
+  ~CSanBuilder();
+
+  CSanBuilder &operator=(const CSanBuilder &other) = delete;
+
+  CSanBuilder *AddSan(uint8_t type, const char *value, size_t value_size);
+
+  // result: pointer to dynamically allocated san (to be deleted with delete[])
+  // or error when size == 0
+  size_t Build(uint8_t **san);
+
+  uint32_t GetNumberOfSan();
+
+private:
+  struct List
+  {
+    char *p;
+    size_t size;
+    uint8_t type;
+    List *next;
+  };
+  size_t total_size = 0;
+  List *entry = nullptr;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/csecure_element.hxx b/include/crypto/controlse/csecure_element.hxx
new file mode 100644
index 000000000..ac79bad10
--- /dev/null
+++ b/include/crypto/controlse/csecure_element.hxx
@@ -0,0 +1,73 @@
+//***************************************************************************
+// apps/include/crypto/controlse/csecure_element.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element.hxx"
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CCertificate;
+class CertificateCatalog;
+class CPublicKey;
+
+class CSecureElement : public ISecureElement
+{
+public:
+  explicit CSecureElement(const char *se05x_device);
+  explicit CSecureElement(int fd);
+  CSecureElement(const CSecureElement &) = delete;
+  CSecureElement(CSecureElement &&) = default;
+  ~CSecureElement();
+
+  CSecureElement &operator=(const CSecureElement &other) = delete;
+
+  bool IsReady() const;
+  bool GenerateKey(struct se05x_generate_keypair_s &args) const;
+  bool SetKey(struct se05x_key_transmission_s &args) const;
+  bool GetKey(struct se05x_key_transmission_s &args) const;
+  bool DeleteKey(uint32_t id) const;
+  bool SetData(struct se05x_key_transmission_s &args) const;
+  bool GetData(struct se05x_key_transmission_s &args) const;
+  bool CreateSignature(struct se05x_signature_s &args) const;
+  bool Verify(struct se05x_signature_s &args) const;
+  bool DeriveSymmetricalKey(struct se05x_derive_key_s &args) const;
+  bool GetUid(struct se05x_uid_s &args) const;
+  bool GetInfo(struct se05x_info_s &args) const;
+
+  CCertificate *GetCertificate(uint32_t keystore_id);
+  CPublicKey *GetPublicKey(uint32_t keystore_id);
+
+private:
+  const int se05x_fd;
+  const bool close_device_at_destructor;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/cserial_number.hxx b/include/crypto/controlse/cserial_number.hxx
new file mode 100644
index 000000000..d8dde8df8
--- /dev/null
+++ b/include/crypto/controlse/cserial_number.hxx
@@ -0,0 +1,62 @@
+//***************************************************************************
+// apps/include/crypto/controlse/cserial_number.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <stddef.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CSerialNumber : ISecureElementObject
+{
+public:
+  static constexpr size_t SERIAL_NUMBER_SIZE = 20;
+  CSerialNumber(const ISecureElement &se, uint32_t keystore_id);
+  CSerialNumber(uint8_t const *serial_number_byte_array);
+
+  bool operator==(CSerialNumber &a) const;
+  bool operator!=(CSerialNumber &a) const;
+  bool operator<(const CSerialNumber &a) const;
+
+  bool IsLoaded() const;
+  bool StoreOnSecureElement(const ISecureElement &se,
+                            uint32_t keystore_id) const;
+  bool LoadFromSecureElement(const ISecureElement &se, uint32_t keystore_id);
+
+  bool
+  GetSerialNumber(uint8_t serial_number_destination[SERIAL_NUMBER_SIZE]) const;
+
+private:
+  bool is_loaded = false;
+  uint8_t serial_number[SERIAL_NUMBER_SIZE];
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/cstring.hxx b/include/crypto/controlse/cstring.hxx
new file mode 100644
index 000000000..4e744f9d4
--- /dev/null
+++ b/include/crypto/controlse/cstring.hxx
@@ -0,0 +1,64 @@
+//***************************************************************************
+// apps/include/crypto/controlse/cstring.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <stddef.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class CString : public ISecureElementObject
+{
+public:
+  CString(const ISecureElement &se, uint32_t keystore_id);
+  CString(char *string, size_t size);
+  CString(const CString &p1);
+  ~CString();
+
+  CString &operator=(const CString &other);
+  bool operator==(CString &a) const;
+  bool operator!=(CString &a) const;
+
+  // return value is string otherwise nullptr
+  // NOTE: need to delete[] return value
+  char *c_str(void) const;
+
+  bool IsLoaded() const;
+  bool StoreOnSecureElement(const ISecureElement &se,
+                            uint32_t keystore_id) const;
+  bool LoadFromSecureElement(const ISecureElement &se, uint32_t keystore_id);
+
+private:
+  size_t m_size = 0;
+  char *m_string = nullptr;
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/isecure_element.hxx b/include/crypto/controlse/isecure_element.hxx
new file mode 100644
index 000000000..ad559f96e
--- /dev/null
+++ b/include/crypto/controlse/isecure_element.hxx
@@ -0,0 +1,71 @@
+//***************************************************************************
+// apps/include/crypto/controlse/isecure_element.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#pragma once
+
+#include "crypto/controlse/isecure_element_object.hxx"
+#include <nuttx/crypto/se05x.h>
+#include <stdint.h>
+
+struct se05x_key_transmission_s;
+struct se05x_signature_s;
+struct se05x_uid_s;
+struct se05x_info_s;
+struct se05x_generate_keypair_s;
+struct se05x_derive_key_s;
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class ISecureElement
+{
+public:
+  virtual ~ISecureElement() = default;
+
+  virtual bool IsReady() const = 0;
+  virtual bool GenerateKey(struct se05x_generate_keypair_s &args) const = 0;
+  virtual bool SetKey(struct se05x_key_transmission_s &args) const = 0;
+  virtual bool GetKey(struct se05x_key_transmission_s &args) const = 0;
+  virtual bool DeleteKey(uint32_t id) const = 0;
+  virtual bool SetData(struct se05x_key_transmission_s &args) const = 0;
+  virtual bool GetData(struct se05x_key_transmission_s &args) const = 0;
+  virtual bool CreateSignature(struct se05x_signature_s &args) const = 0;
+  virtual bool Verify(struct se05x_signature_s &args) const = 0;
+  virtual bool DeriveSymmetricalKey(struct se05x_derive_key_s &args) const = 0;
+  virtual bool GetUid(struct se05x_uid_s &args) const = 0;
+  virtual bool GetInfo(struct se05x_info_s &args) const = 0;
+
+  virtual bool Set(uint32_t keystore_id,
+                   const ISecureElementObject &object) const
+  {
+    return object.StoreOnSecureElement(*this, keystore_id);
+  }
+};
+} // namespace Controlse
diff --git a/include/crypto/controlse/isecure_element_object.hxx b/include/crypto/controlse/isecure_element_object.hxx
new file mode 100644
index 000000000..ecff59015
--- /dev/null
+++ b/include/crypto/controlse/isecure_element_object.hxx
@@ -0,0 +1,51 @@
+//***************************************************************************
+// apps/include/crypto/controlse/isecure_element_object.hxx
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.  The
+// ASF licenses this file to you 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.
+//
+//**************************************************************************
+
+// Copyright 2024 NXP
+
+#pragma once
+
+//***************************************************************************
+// Included Files
+//***************************************************************************
+
+#include <stdint.h>
+
+namespace Controlse
+{
+
+//***************************************************************************
+// Class definitions
+//***************************************************************************
+
+class ISecureElement;
+
+class ISecureElementObject
+{
+public:
+  virtual ~ISecureElementObject() = default;
+  virtual bool IsLoaded() const = 0;
+  virtual bool StoreOnSecureElement(const ISecureElement &se,
+                                    uint32_t keystore_id) const = 0;
+  virtual bool LoadFromSecureElement(const ISecureElement &se,
+                                     uint32_t keystore_id)
+      = 0;
+};
+} // namespace Controlse