How to generate a CSR from Private Key

Hi there,

I’m tryng to generate a Certificate Signing Request (CSR) in my embedded system via mbedTLS.
When I will have generate the CSR, my goal is to print on the serial interface the CSR in PEM format.

At the moment I’m able to generate a private key with “mbedtls_rsa_gen_key”.

How can I proceed to generate the CSR?
I found this example but I prefer to avoid to write the key and CSR on a file.

Is it possibile to generate the CSR without the use of file?

Thanks for the help in advance.

BR,
Federico

Hi Federico,
The example you referenced writes the CSR into a buffer, and then writes the buffer to a file. In the write_certificate_request assisstant function of hte example, you can just return after calling mbedtls_x509write_csr_pem()
Regards,
Mbed TLS Team member
Ron

Hi Ron,

thanks for the reply!

How I can load the private key? At the moment I don’t store the private key on a file.

I have only mbedtls_rsa_context.

Is it possible to load the private key from the context?

Thanks in advance.

BR,
Federico

Hi Federiko,
The example you referenced parses a key into a mbedtls_pk_context struct, and uses it to set the key, using mbedtls_x509write_csr_set_key().
It is better you use the PK wrap functionality, and store your key in mbedtls_pk_context .
Note that this context is itself the private key already loaded.
Regards,
Mbed TLS Team member
Ron

Hi Ron,

How can I store the private key into mbedtls_pk_context?
Is there a function or I should write a wrapper?

Thanks for your help

Hi Federico,
I don’t quite understand your question.
If you follow the gen_key example, instead of the rsa_gen_key, you will generate the key ( given the correct parameters it will be rsa key ) into the mbedtls_pk_context.
If you already have the key, you can look at the key_app example on how to load the key.
Regards,
Mbed TLS Team member
Ron

Hi Ron,

Oh, Maybe I followed the wrong example?

I’m sorry, but I think that I should convert the RSA context into the pk context.
Now I’m looking into the other example.

Just one clarification, I followed the example and I can obtain the PK context with the function mbedtls_pk_setup. Should I proceed with the creation of the RSA key (mbedtls_rsa_gen_key)?

Thanks again!

Hi Ron,

I’m here again to ask your help.

I developed my code but when I execute the function mbedtls_x509write_csr_pem I get back this error code: -17168.

I don’t undestand this error.

I built a module that expose this function MBEDTLS_GenerateRsaPrivateKey() that I use to generate the private key and CSR.

This is my code:

#include "mbedtls.h"
#include "mbedtls/config.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/bignum.h"
#include "mbedtls/x509.h"
#include "mbedtls/rsa.h"
#include "mbedtls/x509_csr.h"

#define MBEDTLS_KEY_SIZE 					(2048)
#define MBEDTLS_EXPONENT 					(65537)

static mbedtls_pk_context 				MBEDTLS_PrivateKeyContext;
static mbedtls_entropy_context 		MBEDTLS_Entropy;
static mbedtls_ctr_drbg_context 	MBEDTLS_CtrDrbg;
static mbedtls_mpi 								MBEDTLS_N;
static mbedtls_mpi 								MBEDTLS_P;
static mbedtls_mpi 								MBEDTLS_Q;
static mbedtls_mpi 								MBEDTLS_D;
static mbedtls_mpi 								MBEDTLS_E;
static mbedtls_mpi 								MBEDTLS_DP;
static mbedtls_mpi 								MBEDTLS_DQ;
static mbedtls_mpi 								MBEDTLS_QP;
static const char*								MBEDTLS_Pers = "gen_key";

static mbedtls_x509write_csr 			MBEDTLS_CsrRequest;
static char												MBEDTLS_PrivateKey[1024];
static unsigned char 							MBEDTLS_CsrPem[4096];

static const char* 								MBEDTLS_SubjectName = "CN=Cert,O=Cefriel TLS,C=IT";

static int MBEDTLS_Printf( const char* buffer, ... );

static int MBEDTLS_Printf( const char* buffer, ... )
{
int 		opResult;
va_list list;

	va_start( list, buffer );

	opResult = Report( buffer, list );

	va_end(list);

	return opResult;

	return 1;
}



uint8_t MBEDTLS_Initialize( void );
uint8_t MBEDTLS_GenerateRsaPrivateKey( void );

uint8_t MBEDTLS_Initialize( void )
{
	uint8_t opResult = APP_TRUE;

	if( mbedtls_platform_set_printf( MBEDTLS_Printf ) != 0 )
	{
		opResult = APP_FALSE;
	}

	return opResult;
}

static uint8_t MBEDTLS_GenerateCsr( void )
{
	int	mbedResult;

	mbedtls_x509write_csr_init( &MBEDTLS_CsrRequest );
	mbedtls_x509write_csr_set_md_alg( &MBEDTLS_CsrRequest, MBEDTLS_MD_SHA256 );
	mbedtls_ctr_drbg_init( &MBEDTLS_CtrDrbg );
	//mbedtls_pk_init( &MBEDTLS_PrivateKeyContext );
	memset( MBEDTLS_PrivateKey, 0, sizeof(MBEDTLS_PrivateKey) );

	UART_PRINT( "Seeding the random number generator...\r\n" );

	mbedtls_entropy_init( &MBEDTLS_Entropy );
	mbedResult = mbedtls_ctr_drbg_seed( &MBEDTLS_CtrDrbg, mbedtls_entropy_func, &MBEDTLS_Entropy, (const unsigned char *)MBEDTLS_Pers, strlen(MBEDTLS_Pers) );

	if( mbedResult == 0 )
	{
		/* Check the subject name for validity */
		UART_PRINT( "Check the subject name for validity\r\n" );
		mbedResult = mbedtls_x509write_csr_set_subject_name( &MBEDTLS_CsrRequest, MBEDTLS_SubjectName );
		if( mbedResult == 0 )
		{
			/* Load the key */
			UART_PRINT( "Loading Private Key" );

			mbedtls_x509write_csr_set_key( &MBEDTLS_CsrRequest, &MBEDTLS_PrivateKeyContext );

			/* Covert CSR in PEM format */
			memset( MBEDTLS_CsrPem, 0, sizeof(MBEDTLS_CsrPem) );

			mbedResult = mbedtls_x509write_csr_pem( &MBEDTLS_CsrRequest, MBEDTLS_CsrPem, sizeof(MBEDTLS_CsrPem), mbedtls_ctr_drbg_random, &MBEDTLS_CtrDrbg );

			if( mbedResult >= 0 )
			{
				UART_PRINT( "CSR conversion to PEM COMPLETED" );
			}
			else
			{
				UART_PRINT( "mbedtls_x509write_csr_pem returned %d - FAILED", mbedResult );
			}
		}
		else
		{
			UART_PRINT( "mbedtls_x509write_csr_set_subject_name returned %d - FAILED", mbedResult );
		}
	}
	else
	{

	}

  mbedtls_x509write_csr_free( &MBEDTLS_CsrRequest );
  mbedtls_pk_free( &MBEDTLS_PrivateKeyContext );
  mbedtls_ctr_drbg_free( &MBEDTLS_CtrDrbg );
  mbedtls_entropy_free( &MBEDTLS_Entropy );

}


uint8_t MBEDTLS_GenerateRsaPrivateKey( void )
{
	int 		mbedResult;

	mbedtls_ctr_drbg_init( &MBEDTLS_CtrDrbg );
	mbedtls_pk_init( &MBEDTLS_PrivateKeyContext );
	memset( MBEDTLS_PrivateKey, 0, sizeof(MBEDTLS_PrivateKey) );

	mbedtls_mpi_init( &MBEDTLS_N );
	mbedtls_mpi_init( &MBEDTLS_P );
	mbedtls_mpi_init( &MBEDTLS_Q );
	mbedtls_mpi_init( &MBEDTLS_D );
	mbedtls_mpi_init( &MBEDTLS_E );
	mbedtls_mpi_init( &MBEDTLS_DP );
	mbedtls_mpi_init( &MBEDTLS_DQ );
	mbedtls_mpi_init( &MBEDTLS_QP );

	UART_PRINT("Seeding the random number generator...\r\n");

	mbedtls_entropy_init( &MBEDTLS_Entropy );

	mbedResult = mbedtls_ctr_drbg_seed( &MBEDTLS_CtrDrbg, mbedtls_entropy_func, &MBEDTLS_Entropy, (const unsigned char *)MBEDTLS_Pers, strlen(MBEDTLS_Pers) );
	if( mbedResult == 0 )
	{
		UART_PRINT( "Generating the private key\r\n" );

		mbedResult = mbedtls_pk_setup( &MBEDTLS_PrivateKeyContext, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));

		if( mbedResult == 0 )
		{
			mbedResult = mbedtls_rsa_gen_key( mbedtls_pk_rsa(MBEDTLS_PrivateKeyContext), mbedtls_ctr_drbg_random, &MBEDTLS_CtrDrbg, MBEDTLS_KEY_SIZE, 65537 );
			if( mbedResult == 0 )
			{
				UART_PRINT( "Private Key COMPLETE\r\n" );

				/* Generate CSR */
				MBEDTLS_GenerateCsr();
				return APP_TRUE;
			}
			else
			{
				UART_PRINT( " FAILED - mbedtls_rsa_gen_key returned -0x%04x", -mbedResult );
			}
		}
		else
		{
			UART_PRINT( "FAILED - mbedtls_pk_setup returned -0x%04x", -mbedResult );
		}
	}
	else
	{
		UART_PRINT( "mbedtls_ctr_drbg_seed returned %d - FAILED\r\n", mbedResult );
	}

	/* Free Resources */
	mbedtls_mpi_free( &MBEDTLS_N );
	mbedtls_mpi_free( &MBEDTLS_P );
	mbedtls_mpi_free( &MBEDTLS_Q );
	mbedtls_mpi_free( &MBEDTLS_D );
	mbedtls_mpi_free( &MBEDTLS_E );
	mbedtls_mpi_free( &MBEDTLS_DP );
	mbedtls_mpi_free( &MBEDTLS_DQ );
	mbedtls_mpi_free( &MBEDTLS_QP );
	mbedtls_ctr_drbg_free( &MBEDTLS_CtrDrbg );
	mbedtls_entropy_free( &MBEDTLS_Entropy );

	return APP_FALSE;
}

Thanks for your help!

BR,

Federico

Hi Federico,
in programs/utils, you will find a utility called strerror that will traqnslate the error code to a readable string, assuming the module is defined in your platform, and that you have MBEDTLS_ERROR_C defined.
If you run this utility with the error code, you will see:

./strerror -17168
Last error was: -0x4310 - RSA - The private key operation failed : BIGNUM - Memory allocation failed

This means that during the key generation, you ran of of heap memory, and that you don’t have any memory leaks.
Please check you have sufficient heap in your platform.
Regards,
Mbed TLS Team member
Ron

1 Like

Hi Ron,

thanks for the reply.

I thought that this error could be related to the dynamic memory because to fit the program into the microcontroller I resized the heap an the stack.

I’ll use the uitlity to better understand the errors.

Thanks for your help and yor time!

BR,
Federico