controlse: add accesslib for the se05x secure element

This commit is contained in:
Andre Heinemans 2024-04-19 12:29:05 +02:00 committed by Xiang Xiao
parent fe12ad9444
commit cecc2e762b
28 changed files with 3335 additions and 1495 deletions

View File

@ -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()

View File

@ -18,8 +18,9 @@ config CRYPTO_CONTROLSE
select MBEDTLS_X509_CSR_WRITE_C select MBEDTLS_X509_CSR_WRITE_C
select MBEDTLS_X509_CRT_WRITE_C select MBEDTLS_X509_CRT_WRITE_C
---help--- ---help---
Enable the controlse utility. This program is used control the Enable the controlse library and utility. It provides an
secure element device access library to the secure element device. The utility can
control the secure element device from the nuttx shell
if CRYPTO_CONTROLSE if CRYPTO_CONTROLSE

View File

@ -18,6 +18,8 @@
# #
############################################################################ ############################################################################
# Copyright 2023, 2024 NXP
include $(APPDIR)/Make.defs include $(APPDIR)/Make.defs
# controlse built-in application info # controlse built-in application info
@ -28,7 +30,8 @@ STACKSIZE = $(CONFIG_CRYPTO_CONTROLSE_STACKSIZE)
# controlse main source # controlse main source
MAINSRC = controlse_main.c MAINSRC = controlse_main.cxx
CSRCS = x509_utils.c mbedtls_extension.c 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 include $(APPDIR)/Application.mk

View File

@ -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

212
crypto/controlse/ccsr.cxx Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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