Added tools for NXP SE05x (secure element)

This commit is contained in:
Andre Heinemans 2023-05-12 12:19:18 +02:00 committed by Xiang Xiao
parent 189d0c803f
commit 8757c6934c
13 changed files with 2084 additions and 0 deletions

41
crypto/controlse/Kconfig Normal file
View File

@ -0,0 +1,41 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config CRYPTO_CONTROLSE
bool "Control Secure Element device"
default n
depends on DEV_SE05X
depends on CRYPTO_MBEDTLS
depends on MBEDTLS_VERSION = "3.4.0"
select MBEDTLS_ECDSA_C
select MBEDTLS_ECP_C
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
select MBEDTLS_PEM_WRITE_C
select MBEDTLS_PK_WRITE_C
select MBEDTLS_X509_CSR_PARSE_C
select MBEDTLS_X509_CSR_WRITE_C
select MBEDTLS_X509_CRT_WRITE_C
---help---
Enable the controlse utility. This program is used control the
secure element device
if CRYPTO_CONTROLSE
config CRYPTO_CONTROLSE_PROGNAME
string "Program name"
default "controlse"
---help---
This is the name of the program that will be used when the NSH ELF
program is installed.
config CRYPTO_CONTROLSE_PRIORITY
int "Controlse utility task priority"
default 100
config CRYPTO_CONTROLSE_STACKSIZE
int "Controlse utility stack size"
default DEFAULT_TASK_STACKSIZE
endif

View File

@ -0,0 +1,23 @@
############################################################################
# apps/crypto/controlse/Make.defs
#
# 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.
#
############################################################################
ifneq ($(CONFIG_CRYPTO_CONTROLSE),)
CONFIGURED_APPS += $(APPDIR)/crypto/controlse
endif

34
crypto/controlse/Makefile Normal file
View File

@ -0,0 +1,34 @@
############################################################################
# apps/crypto/controlse/Makefile
#
# 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.
#
############################################################################
include $(APPDIR)/Make.defs
# controlse built-in application info
PROGNAME = $(CONFIG_CRYPTO_CONTROLSE_PROGNAME)
PRIORITY = $(CONFIG_CRYPTO_CONTROLSE_PRIORITY)
STACKSIZE = $(CONFIG_CRYPTO_CONTROLSE_STACKSIZE)
# controlse main source
MAINSRC = controlse_main.c
CSRCS = x509_utils.c mbedtls_extension.c
include $(APPDIR)/Application.mk

View File

@ -0,0 +1,737 @@
/****************************************************************************
* 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,310 @@
/****************************************************************************
* 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

@ -0,0 +1,40 @@
/****************************************************************************
* 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

@ -0,0 +1,350 @@
/****************************************************************************
* 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

@ -0,0 +1,54 @@
/****************************************************************************
* 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

@ -136,6 +136,44 @@ config MBEDTLS_NET_C
default y if LIBC_NETDB
default n if !LIBC_NETDB
config MBEDTLS_ECDSA_C
bool "Enable the elliptic curve DSA library."
default n
config MBEDTLS_ECP_C
bool "Enable the elliptic curve over GF(p) library."
default n
config MBEDTLS_ECP_DP_SECP256R1_ENABLED
bool "Enables specific curves within the Elliptic Curve module."
default n
config MBEDTLS_PEM_WRITE_C
bool "Enable PEM encoding / writing."
default n
config MBEDTLS_PK_WRITE_C
bool "Enable the generic public (asymmetric) key writer."
default n
config MBEDTLS_X509_CREATE_C
bool "Enable X.509 core for creating certificates."
default n
config MBEDTLS_X509_CRT_WRITE_C
bool "Enable creating X.509 certificates."
select MBEDTLS_X509_CREATE_C
default n
config MBEDTLS_X509_CSR_WRITE_C
bool "Enable creating X.509 Certificate Signing Requests (CSR)."
select MBEDTLS_X509_CREATE_C
default n
config MBEDTLS_X509_CSR_PARSE_C
bool "Enable X.509 Certificate Signing Request (CSR) parsing."
default n
if CRYPTO_CRYPTODEV
config MBEDTLS_ALT

30
testing/setest/Kconfig Normal file
View File

@ -0,0 +1,30 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config TESTING_SETEST
bool "Secure Element driver test"
default n
depends on DEV_SE05X
---help---
Enable the Secure Element driver test
if TESTING_SETEST
config TESTING_SETEST_PROGNAME
string "Program name"
default "setest"
---help---
This is the name of the program that will be used when the NSH ELF
program is installed.
config TESTING_SETEST_PRIORITY
int "setest utility task priority"
default 100
config TESTING_SETEST_STACKSIZE
int "setest utility stack size"
default DEFAULT_TASK_STACKSIZE
endif

23
testing/setest/Make.defs Normal file
View File

@ -0,0 +1,23 @@
############################################################################
# apps/testing/setest/Make.defs
#
# 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.
#
############################################################################
ifneq ($(CONFIG_TESTING_SETEST),)
CONFIGURED_APPS += $(APPDIR)/testing/setest
endif

33
testing/setest/Makefile Normal file
View File

@ -0,0 +1,33 @@
############################################################################
# apps/testing/setest/Makefile
#
# 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.
#
############################################################################
include $(APPDIR)/Make.defs
# setest built-in application info
PROGNAME = $(CONFIG_TESTING_SETEST_PROGNAME)
PRIORITY = $(CONFIG_TESTING_SETEST_PRIORITY)
STACKSIZE = $(CONFIG_TESTING_SETEST_STACKSIZE)
# setest main source
MAINSRC = setest.c
include $(APPDIR)/Application.mk

371
testing/setest/setest.c Normal file
View File

@ -0,0 +1,371 @@
/****************************************************************************
* apps/testing/setest/setest.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 <fcntl.h>
#include <libgen.h>
#include <nuttx/crypto/se05x.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DEFAULT_SETTINGS \
{ \
.se05x_dev = default_se05x_device, .skip_process = FALSE, \
.base_id = 0x230000 \
}
/****************************************************************************
* Private Types
****************************************************************************/
struct settings_t
{
FAR char *se05x_dev;
bool skip_process;
uint32_t base_id;
};
/****************************************************************************
* Private Data
****************************************************************************/
static char default_se05x_device[] = "/dev/se05x";
/****************************************************************************
* Private Functions
****************************************************************************/
static void print_usage(FAR FILE *f, char *prg)
{
fprintf(f, "%s - Secure Element Test\n", prg);
fprintf(f, "\nUsage: %s [options] <secure element device>\n", prg);
fprintf(f, "Options:\n");
fprintf(f, " -b <id> (use base address <id>\n");
fprintf(f, " default = 0x230000)\n");
}
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, "b:h")) != -1) && (result == 0))
{
switch (opt)
{
case 'b':
settings->base_id = (uint32_t)strtoul(optarg, NULL, 0);
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))
{
settings->se05x_dev = default_se05x_device;
/* if device is specified as positional argument */
if (optind != argc)
{
settings->se05x_dev = argv[optind];
}
}
return result;
}
static uint32_t get_se05x_id(FAR struct settings_t *settings, uint32_t id)
{
return settings->base_id + id;
}
static void print_result(bool success)
{
if (success)
{
puts(" SUCCESS");
}
else
{
puts(" FAIL");
}
}
static int invert_result(int result)
{
return result != 0 ? 0 : -1;
}
static int run_tests(int fd, FAR struct settings_t *settings)
{
int result = 0;
puts("Setup");
for (uint32_t id = get_se05x_id(settings, 1);
id < get_se05x_id(settings, 5); id++)
{
/* result is neglected because already empty entries result with
* errors
*/
(void)ioctl(fd, SEIOC_DELETE_KEY, id);
}
puts("Generate 3 keypairs");
for (uint32_t id = get_se05x_id(settings, 1);
(id < get_se05x_id(settings, 4)) && (result == 0); id++)
{
struct se05x_generate_keypair_s args = {
.id = id, .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256
};
result = ioctl(fd, SEIOC_GENERATE_KEYPAIR, &args);
}
print_result(result == 0);
uint8_t public_key[300];
size_t public_key_size;
if (result == 0)
{
puts("Read from pub #1");
struct se05x_key_transmission_s args = {
.entry = {.id = get_se05x_id(settings, 1),
.cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256},
.content = {.buffer = public_key,
.buffer_size = sizeof(public_key)}
};
result = ioctl(fd, SEIOC_GET_KEY, &args);
public_key_size = args.content.buffer_content_size;
print_result(result == 0);
}
if (result == 0)
{
puts("Write to pub #4");
struct se05x_key_transmission_s args = {
.entry = {.id = get_se05x_id(settings, 4),
.cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256},
.content = {.buffer = public_key,
.buffer_size = public_key_size,
.buffer_content_size = public_key_size}
};
result = ioctl(fd, SEIOC_SET_KEY, &args);
print_result(result == 0);
}
uint8_t hash[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31
};
uint8_t signature[300];
size_t signature_content_size;
if (result == 0)
{
puts("Create signature with priv #1");
struct se05x_signature_s args = {
.key_id = get_se05x_id(settings, 1),
.algorithm = SE05X_ALGORITHM_SHA256,
.tbs = {.buffer = hash,
.buffer_size = sizeof(hash),
.buffer_content_size = sizeof(hash)},
.signature = {.buffer = signature,
.buffer_size = sizeof(signature)},
};
result = ioctl(fd, SEIOC_CREATE_SIGNATURE, &args);
signature_content_size = args.signature.buffer_content_size;
print_result(result == 0);
}
if (result == 0)
{
puts("Verify signature with pub #4");
struct se05x_signature_s args = {
.key_id = get_se05x_id(settings, 4),
.algorithm = SE05X_ALGORITHM_SHA256,
.tbs = {.buffer = hash,
.buffer_size = sizeof(hash),
.buffer_content_size = sizeof(hash)},
.signature = {.buffer = signature,
.buffer_content_size = signature_content_size},
};
result = ioctl(fd, SEIOC_VERIFY_SIGNATURE, &args);
print_result(result == 0);
}
if (result == 0)
{
puts("Verification of signature with pub #2 should be dissapproved");
struct se05x_signature_s args = {
.key_id = get_se05x_id(settings, 2),
.algorithm = SE05X_ALGORITHM_SHA256,
.tbs = {.buffer = hash, .buffer_size = sizeof(hash)},
.signature = {.buffer = signature,
.buffer_content_size = signature_content_size},
};
result = invert_result(ioctl(fd, SEIOC_VERIFY_SIGNATURE, &args));
print_result(result == 0);
}
uint8_t symm_key_a[32];
if (result == 0)
{
puts("Derive symm key #a from priv #1 and pub #2");
struct se05x_derive_key_s args = {
.private_key_id = get_se05x_id(settings, 1),
.public_key_id = get_se05x_id(settings, 2),
.content = {.buffer = symm_key_a,
.buffer_size = sizeof(symm_key_a)},
};
result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args);
print_result(result == 0);
}
uint8_t symm_key_b[32];
if (result == 0)
{
puts("Derive symm key #b from priv #2 and pub #1");
struct se05x_derive_key_s args = {
.private_key_id = get_se05x_id(settings, 2),
.public_key_id = get_se05x_id(settings, 1),
.content = {.buffer = symm_key_b,
.buffer_size = sizeof(symm_key_b)},
};
result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args);
print_result(result == 0);
}
uint8_t symm_key_c[32];
if (result == 0)
{
puts("Derive symm key #c from priv #1 and pub #3");
struct se05x_derive_key_s args = {
.private_key_id = get_se05x_id(settings, 1),
.public_key_id = get_se05x_id(settings, 3),
.content = {.buffer = symm_key_c,
.buffer_size = sizeof(symm_key_c)},
};
result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args);
print_result(result == 0);
}
if (result == 0)
{
puts("Symm key #a and #b should be equal");
result = memcmp(symm_key_a, symm_key_b, sizeof(symm_key_a));
print_result(result == 0);
}
if (result == 0)
{
puts("Symm key #a and #c should be different");
result =
invert_result(memcmp(symm_key_a, symm_key_c, sizeof(symm_key_a)));
print_result(result == 0);
}
if (result == 0)
{
puts("All tests succeeded!\n");
}
return result;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int main(int argc, FAR char *argv[])
{
struct settings_t settings = DEFAULT_SETTINGS;
int result = parse_arguments(argc, argv, &settings);
int fd;
if ((result == 0) && (!settings.skip_process))
{
fd = open(settings.se05x_dev, O_RDONLY);
if (fd == -1)
{
result = -ENODEV;
}
else
{
run_tests(fd, &settings);
close(fd);
}
}
if (result != 0)
{
fprintf(stderr, "err %i: %s\n", -result, strerror(-result));
}
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}