Cannot Create Self-Signed Certificate Using Hardcoded PEM RSA Private Key

Hi MbedTLS Team,

May we ask for your assistance to check on what could be the issue that the firmware is facing. We are trying to create a self-signed certificate. PEM key is already hardcoded and using a dummy RNG generator.

It seems that there is problem with mbedtls_pk_parse_key function, and there is an error -17280.

The code is pasted below and we are using STM32H750 as the CPU.

Hoping for your assistance.

Thank you.

Johnson.

#include “mbedtls/x509_crt.h”

#include “mbedtls/x509_csr.h”

#include “mbedtls/pk.h”

#include “mbedtls/ctr_drbg.h”

#include “mbedtls/entropy.h”

#include “mbedtls/x509.h”

#include “mbedtls/pem.h”

#include “stm32h7xx_hal.h”

#include “stm32h7xx_hal_rng.h”

#include <string.h>

#include <stdio.h>

#include “mbedtls/error.h”

#define CERT_BUF_SIZE 4096

unsigned char cert_buf[CERT_BUF_SIZE];

const char HARD_CODED_PRIVATE_KEY_PEM =

“-----BEGIN RSA PRIVATE KEY-----\n”

“MIIEowIBAAKCAQEAwHnKhHgQb7qA44cZ4/vZpR9wA3M9TxGcb3vRbtX0nv0KOCGr\n”

“lLz3zvDJ+5ME4apcKNkz6Z2zSnYoknXNlxT+ycAN9+YEKyG38vblCwrLLghvKZMP\n”

“3yL3ReSgXAj6cLk1ybM3NdEwrX4vNKPY+pPzCVaLC8Grf5ylmUByKeex5Ai0vZHe\n”

“oQhWPH46BdTzZXv7SkcdNKEJgZGjEZz8h6epuhOiBF3zU17KfglE2gYKEQUOyzvQ\n”

“h3tZoqo1GLsLUoOeTDGBsZJK+CtDccIQw9PA8TYFksOJxOVIs+TfrT5Yg1uRPQDu\n”

“99vY2HzRf68Bd+AzQO/ELDQqRlgCeuMXdEilWQIDAQABAoIBAEx03mYecLB7UHRR\n”

“Wjlj+DUrbGFQLfz2q0u7IfoFhdKr50z5hQ+KNDsDaLa2fnUt8DoT0LEoyBaSxQdT\n”

“fOYvHF/OK1GzWKP7ssLNmHi20S3++q0WTWIt+YiqOT6Ck5W3Z0TLZPyaR1ul5kV6\n”

“DLC0TQiqIuVt7UsORyGvcT3yFLFwC4HFsfkVKhUwNkCOk/ntZwrwbAIVSRFmf62V\n”

“HsoD8KwXN4x7FEPHDC2+a77z3vPNvUmQuuqG/7vxBAepKfO4znv8LGJ0AG/WKwKc\n”

“gVOr88Zxz+E+U0d3QqYIbFvYTb59fsBjvV7T4mhw9NH7VOZRuD1nAXF9oaSC8quU\n”

“SujFzSECgYEA5x6URr3TVNwnrBxEA91ncMZ9uN6zreBX7wKZOfch5G8YqaOjAAOw\n”

“z5n6TTmbEXJebKzOy5Dqkqk2v+LQUFEQeAfCOZs0A+xt82OQ2HQefbJPehEm4yJG\n”

“2UwzQ8ZMR6zMI5PlRr0+gyfj5P4fqKY3Aq2A9if8r+RZrNpjH1ct+CMCgYEA1sHc\n”

“Bb4T41BGCEZGn3S9sbIUF9qD7vayGkyH7bdSg6lsQMrxRkb2+DTj0Ul6zrxvdWkR\n”

“zq26Oj2opUXFGUYY7zNwHdvOL1S+hK2TQ8dAfEYYJtyIqZAlHto/3F7gKvCcxMTF\n”

“Oayli0Z47ryYRX7baxM6t4HTBMiMiT0SZvPZHk0CgYAGFkfEjNGVxOTaA+qEbZnT\n”

“iyUmRY7TeZgaYlPzFyYTy6+KCPx3rqKShWN+1ZP/NMKj+/eCr6zSKKldd1hFMX+X\n”

“B3ErkLaY8/1OyFq6WgnJksJmhxYPuH5zdk/9H+4kjNT9ZjKFD6mnkQ0DbTjkLoRi\n”

“X7SB5EyxUTBb3m3Lhnc8oQKBgH8MnyqF6skMvRVd5CVNaYATXFD0ayKaHxyOZhBa\n”

“Gbd4vXZrE31VvZuRzGAMZxNc0PGOXdujgb7sneI1GhPqDJDNNxZkMMskV4gc9JoR\n”

“s8HhrbU8F1cvkCIeGVunmp0iS04b+LyztlZlKPIm0Y/yEMD5iLk8uxwjPUFZ2l5v\n”

“TAlxAoGBAI82j+g4ANRxnImcc6Q7sE3b7fj7a68y4+lAvFAY81kRzBkhqNNeOErR\n”

“ff61flXtqmmrRB9sTiZm+FChGwnsG7FXSlsfLsUEyZXMMY6hRmgCRwQPDgklrZCR\n”

“1W/THmnKvP0+N0CAgPdxox+2Drw5Z+ZBC1cC7Hq0kR57N+LrMcWv\n”

“-----END RSA PRIVATE KEY-----\n”;

RNG_HandleTypeDef hrng;

int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen)

{

uint32_t random;

size_t i = 0;



for (i = 0; i < len; i += sizeof(random)) {

    if (HAL_RNG_GenerateRandomNumber(&hrng, &random) != HAL_OK)

        return -1;



    size_t copy_len = (len - i >= sizeof(random)) ? sizeof(random) : (len - i);

    memcpy(output + i, &random, copy_len);

}



\*olen = len;

return 0;

}

void RNG_Init(void)

{

\__HAL_RCC_RNG_CLK_ENABLE();

hrng.Instance = RNG;

if (HAL_RNG_Init(&hrng) != HAL_OK) {

    printf("RNG init failed\\n");

}

}

// Added on September 19, 2025

int fake_entropy_source(void *data, unsigned char *output, size_t len, size_t *olen)

{

static const unsigned char fake_entropy\[32\] = {

    0x01, 0x23, 0x45, 0x67,

    0x89, 0xAB, 0xCD, 0xEF,

    0x10, 0x32, 0x54, 0x76,

    0x98, 0xBA, 0xDC, 0xFE,

    0x11, 0x22, 0x33, 0x44,

    0x55, 0x66, 0x77, 0x88,

    0x99, 0xAA, 0xBB, 0xCC,

    0xDD, 0xEE, 0xFF, 0x00

};



if (len > sizeof(fake_entropy))

    len = sizeof(fake_entropy);



memcpy(output, fake_entropy, len);

\*olen = len;

return 0;

}

int generate_self_signed_cert(unsigned char *output_buf, size_t buf_size,

                          const char \*common_name,

                          const char \*not_before,

                          int validity_years)

{

int ret;

mbedtls_pk_context key;

mbedtls_x509write_cert crt;

mbedtls_entropy_context entropy;

mbedtls_ctr_drbg_context ctr_drbg;

const char \*pers = "selfsign";

char subject_name\[256\];

char not_after\[16\];



// Compute notAfter from notBefore + validity_years

int year;

sscanf(not_before, "%4d", &year);

year += validity_years;

snprintf(not_after, sizeof(not_after), "%04d%s", year, not_before + 4);



mbedtls_pk_init(&key);

mbedtls_x509write_crt_init(&crt);

mbedtls_entropy_init(&entropy);

mbedtls_ctr_drbg_init(&ctr_drbg);



// ret = mbedtls_entropy_add_source(&entropy, mbedtls_hardware_poll, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);



// Changed on September 19, 2025 // This is to use the fake entropy

ret = mbedtls_entropy_add_source(&entropy, fake_entropy_source, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG);





if (ret != 0) {

    printf("Entropy source registration failed: -0x%04X\\n", -ret);

    return ret;

}



ret = mbedtls_pk_parse_key(&key,

                           (const unsigned char \*)HARD_CODED_PRIVATE_KEY_PEM,

                           strlen(HARD_CODED_PRIVATE_KEY_PEM) + 1,

                           NULL, 0);

if (ret != 0) return ret;



ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,

                            (const unsigned char \*)pers, strlen(pers));

if (ret != 0) return ret;



mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);

mbedtls_x509write_crt_set_subject_key(&crt, &key);

mbedtls_x509write_crt_set_issuer_key(&crt, &key);



snprintf(subject_name, sizeof(subject_name), "O=COMPANY INC,CN=%s", common_name);



ret = mbedtls_x509write_crt_set_subject_name(&crt, subject_name);

if (ret != 0) return ret;



ret = mbedtls_x509write_crt_set_issuer_name(&crt, subject_name);

if (ret != 0) return ret;



mbedtls_mpi serial;

mbedtls_mpi_init(&serial);

ret = mbedtls_mpi_fill_random(&serial, 16, mbedtls_ctr_drbg_random, &ctr_drbg);

if (ret != 0) return ret;



mbedtls_x509write_crt_set_serial(&crt, &serial);

mbedtls_mpi_free(&serial);



ret = mbedtls_x509write_crt_set_validity(&crt, not_before, not_after);

if (ret != 0) return ret;



mbedtls_x509write_crt_set_basic_constraints(&crt, 0, -1);

mbedtls_x509write_crt_set_key_usage(&crt, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_ENCIPHERMENT);



memset(output_buf, 0, buf_size);

ret = mbedtls_x509write_crt_pem(&crt, output_buf, buf_size,

                                mbedtls_ctr_drbg_random, &ctr_drbg);



mbedtls_pk_free(&key);

mbedtls_x509write_crt_free(&crt);

mbedtls_ctr_drbg_free(&ctr_drbg);

mbedtls_entropy_free(&entropy);



return ret;

}

int main(void)

{

HAL_Init();

RNG_Init();



// unsigned char cert_buf\[CERT_BUF_SIZE\];

const char \*cn = "1.1.1.1";

const char \*not_before = "20250918000000";

int validity_years = 5;



int ret = generate_self_signed_cert(cert_buf, sizeof(cert_buf), cn, not_before, validity_years);

if (ret == 0)

    printf("Certificate generated successfully:\\n%s\\n", cert_buf);

else {

    char error_buf\[100\];

    mbedtls_strerror(ret, error_buf, sizeof(error_buf));

    printf("Certificate generation failed: -0x%04X: %s\\n", -ret, error_buf);

}

while (1);

}