nuttx-apps/crypto/controlse/x509_utils.c
2023-08-22 10:12:31 +08:00

351 lines
10 KiB
C

/****************************************************************************
* 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;
}