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