I’m using mbedTLS to verify previously generated certificates:
- Self signed root certificate
- Intermediate certificate signed by the root certificate
- Device certificate signed by the intermediate certificate
Certificates are generated using OpenSSL:
Root cert:
openssl ecparam -genkey -name prime256v1 -out %ROOT_CA_DIR%\root_private.key
openssl req -new -x509 -SHA256 -days 3650 -key %ROOT_CA_DIR%\root_private.key -nodes -out %ROOT_CA_DIR%\root_cert.pem -subj "/C=US/O=Wcompany/OU=ATDE/CN=ROOT-CN"
openssl x509 -in %ROOT_CA_DIR%\root_cert.pem -out %ROOT_CA_DIR%\root_cert.der -outform DER
Intermediate cert:
openssl ecparam -genkey -name prime256v1 -out %CHAIN_DIR%\ica_private.key
openssl req -new -SHA256 -key %CHAIN_DIR%\ica_private.key -nodes -out %CHAIN_DIR%\ica_sign_req.csr -subj "/C=US/O=Wcompany/OU=SubComp/CN=INTERIM-CN"
openssl x509 -req -SHA256 -extfile v3_intermediate_ca.ext -days 365 -in %CHAIN_DIR%\ica_sign_req.csr -CA %ROOT_CA_DIR%\root_cert.pem -CAkey %ROOT_CA_DIR%\root_private.key -CAcreateserial -out %CHAIN_DIR%\ica_cert.pem
openssl x509 -in %CHAIN_DIR%\ica_cert.pem -out %CHAIN_DIR%\ica_cert.der -outform DER
Device cert:
openssl ecparam -genkey -name prime256v1 -out %CHAIN_DIR%\device_private.key
openssl req -new -SHA256 -key %CHAIN_DIR%\device_private.key -nodes -out %CHAIN_DIR%\device_sign_req.csr -subj "/C=US/O=Wcompany/OU=SubComp/CN=MyDevice"
openssl x509 -req -SHA256 -days 365 -in %CHAIN_DIR%\device_sign_req.csr -CA %CHAIN_DIR%\ica_cert.pem -CAkey %CHAIN_DIR%\ica_private.key -CAcreateserial -out %CHAIN_DIR%\device_cert.pem
openssl x509 -in %CHAIN_DIR%\device_cert.pem -out %CHAIN_DIR%\device_cert.der -outform DER
openssl ec -in %CHAIN_DIR%\device_private.key -outform DER -out %CHAIN_DIR%\device_private.der
Afterwards, raw data in the .der files is converted to char array using python:
import binascii
files_list = list()
files_list.append(("root_cert.der", "root_array"))
files_list.append(("ica_cert.der", "ica_array"))
files_list.append(("device_cert.der", "device_array"))
main_h = "certificates.h"
for input_file, output_name in files_list:
with open(input_file, "rb") as file:
der_bytes = file.read()
hex_string = binascii.hexlify(der_bytes).decode("utf-8")
with open(main_h, "a") as file:
file.write(f"const unsigned char {output_name}[] = {{\n")
for i in range(0, len(hex_string), 2):
file.write(f"0x{hex_string[i:i+2]}, ")
if i % 32 == 30:
file.write("\n")
file.write(f"\n}};\n\n")
Next, I’ve copied the “const unsigned char root_cert” and “const unsigned char ica_cert” from the “certificates.h” and created the following code:
#include <stdint.h>
#include <stdlib.h>
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/x509_csr.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
const unsigned char root_cert[] = {0x30, ... 0xf7};
const unsigned char ica_cert[] = {0x30, ... 0x01};
extern void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len);
uint32_t flags = 0;
unsigned char local_buf[32*1024];
int main(void) {
mbedtls_memory_buffer_alloc_init(local_buf, 32*1024);
mbedtls_x509_crt root_cert_struct;
mbedtls_x509_crt_init(&root_cert_struct);
mbedtls_x509_crt ica_cert_struct;
mbedtls_x509_crt_init(&ica_cert_struct);
if (mbedtls_x509_crt_parse_der(&root_cert_struct, root_cert, sizeof(root_cert)) != 0) {
mbedtls_x509_crt_free(&root_cert_struct);
fail_blink(); }
else { success_blink(); }
if (mbedtls_x509_crt_parse_der(&ica_cert_struct, ica_cert, sizeof(ica_cert)) != 0) {
mbedtls_x509_crt_free(&ica_cert_struct);
fail_blink(); }
else { success_blink(); }
// Load the self-signed certificate into a certificate structure
if (mbedtls_x509_crt_verify(&ica_cert_struct, &root_cert_struct, NULL, NULL, &flags, NULL, NULL) != 0) {
mbedtls_x509_crt_free(&ica_cert_struct);
mbedtls_x509_crt_free(&root_cert_struct);
fail_blink(); }
else { success_blink(); }
mbedtls_x509_crt_free(&ica_cert_struct);
mbedtls_x509_crt_free(&root_cert_struct);
while (1) { // do something }
}
Also the medTLS_config.h file contains the following:
#define MBEDTLS_CONFIG_VERSION 0x03010000
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
#define MBEDTLS_ECP_DP_CURVE448_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_ERROR_STRERROR_DUMMY
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_PSA_CRYPTO_CONFIG
#define MBEDTLS_AES_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_ERROR_C
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_MD5_C
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
#define MBEDTLS_OID_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_PSA_CRYPTO_C
#define MBEDTLS_RIPEMD160_C
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA224_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_CRL_PARSE_C
#define MBEDTLS_X509_CSR_PARSE_C
With this parsing of certificate data passes without issues. But:
- The issue I’m having is that when I use mbedtls_x509_crt_verify() with root_cert_struct for the first two arguments, everything is working fine.
- But if I set ica_cert_struct and root_cert_struct for the first two arguments respectively, the program execution stops on the mbedtls_x509_crt_verify() call. During debugging I’m finding that this function calls another function … and so on until the file “bignum.c” in function “mbedtls_mpi_grow()” line:
if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL )
When I enter the mbedtls_calloc() it ends up in the file “memory_buffer_alloc.c”, function “buffer_alloc_calloc()” line:
mbedtls_exit( 1 );
And program execution stops there, never continuing to another line.
Can someone help me with this? I don’t understand why it would stop executing at the exit function.