351 lines
10 KiB
C
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;
|
|
}
|