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