mbedtls CSR in ESP32

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

mbedtls CSR in ESP32

Postby 16aa00 » Fri Sep 21, 2018 4:05 am

Hello,

I have generated RSA public and private key pair and they are saved in SPIFFS file in ESP32. Now I am trying to generate CSR using the RSA private key generated above. For that, I am using mbedtls APIs and I am following this example
https://github.com/ARMmbed/mbedtls/blob ... cert_req.c

I am getting an error while loading the saved private key file("/spiffs/client.key") to parse using mbedtls_pk_parse_keyfile() . This returns me an error -15616. Could anyone of you please help me to know what this error means and how to solve this?

I am uploading a relevant part of my code. Any help would be kindly appreciated.

Thank you

Code: Select all

#include "mbedtls/rsa.h"
#include "mbedtls/pk.h"
#include "mbedtls/sha1.h"
#include "mbedtls/platform.h"
#include "mbedtls/config.h"
#include "mbedtls/oid.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/x509_csr.h"
#include "mbedtls/error.h"
#include<string.h>
#include "mbedtls/md.h"
#include "mbedtls/entropy.h"
#include "mbedtls/bignum.h"
#include "SPIFFS.h"
#include "FS.h"
#include <SD.h>
#include <SPI.h>

#define DFL_FILENAME            "/spiffs/client.key"
#define DFL_DEBUG_LEVEL         0
#define DFL_OUTPUT_FILENAME     "/spiffs/client.csr"
#define DFL_SUBJECT_NAME        "CN=Cert,O=mbed TLS,C=UK"
#define DFL_KEY_USAGE           0
#define DFL_NS_CERT_TYPE        0

#define mbedtls_printf printf

struct options
{
    const char *filename;       /* filename of the key file             */
    int debug_level;            /* level of debugging                   */
    const char *output_file;    /* where to store the constructed key file  */
    const char *subject_name;   /* subject name for certificate request */
    unsigned char key_usage;    /* key usage flags                      */
    unsigned char ns_cert_type; /* NS cert type                         */
} opt;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println();
  int ret = 1;
  mbedtls_entropy_context entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  
  char buf[1024];
  
  mbedtls_ctr_drbg_init( &ctr_drbg );
  mbedtls_entropy_init( &entropy );
  if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                             (const unsigned char *) pers,
                             strlen( pers ) ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d", ret );
      return;
  }
  
  mbedtls_pk_context key;
  mbedtls_x509write_csr req;

  mbedtls_x509write_csr_init( &req );
  mbedtls_x509write_csr_set_md_alg( &req, MBEDTLS_MD_SHA256 );
  mbedtls_pk_init( &key );
  memset( buf, 0, sizeof( buf ) );
  
  opt.filename            = DFL_FILENAME;
  opt.debug_level         = DFL_DEBUG_LEVEL;
  opt.output_file         = DFL_OUTPUT_FILENAME;
  opt.subject_name        = DFL_SUBJECT_NAME;
  opt.key_usage           = DFL_KEY_USAGE;
  opt.ns_cert_type        = DFL_NS_CERT_TYPE;

  if( opt.key_usage )
      mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );

  if( opt.ns_cert_type )
      mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );

  mbedtls_printf( "  . Seeding the random number generator..." );
  
  mbedtls_entropy_init( &entropy );
  if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                             (const unsigned char *) pers,
                             strlen( pers ) ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d", ret );
      return;
  }

  mbedtls_printf( " ok\n" );

  /*
   * 1.0. Check the subject name for validity
   */
  mbedtls_printf( "  . Checking subject name..." );

  if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_x509write_csr_set_subject_name returned %d", ret );
      return;
  }

  mbedtls_printf( " ok\n" );

  /*
   * 1.1. Load the key
   */
  mbedtls_printf( "  . Loading the private key ..." );
  SPIFFS.begin();

  ret = mbedtls_pk_parse_keyfile( &key, opt.filename, NULL );
  Serial.println(ret);

  if( ret != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned %d", ret );
      return;
  }

  mbedtls_x509write_csr_set_key( &req, &key );

  mbedtls_printf( " ok\n" );

  /*
   * 1.2. Writing the request
   */
  mbedtls_printf( "  . Writing the certificate request ..." );

  if( ( ret = write_certificate_request( &req, opt.output_file,
                                         mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  write_certifcate_request %d", ret );
      return;
  }

  mbedtls_printf( " ok\n" );

  mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
  mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &DP );
  mbedtls_mpi_free( &DQ ); mbedtls_mpi_free( &QP );
  mbedtls_rsa_free( &rsa );
  mbedtls_ctr_drbg_free( &ctr_drbg );
  mbedtls_entropy_free( &entropy );
  
  }

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: mbedtls CSR in ESP32

Postby ESP_Angus » Mon Sep 24, 2018 5:32 am

mbedTLS errors are given in hex in the source, so - 15616 = -0x3d00

Code: Select all

#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT  -0x3D00  /**< Invalid key tag or value. */
So likely the problem is somewhere in the key file content?

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

Re: mbedtls CSR in ESP32

Postby 16aa00 » Mon Sep 24, 2018 7:29 am

Thank you for your response.

The format of private key file is attached. I used the ".key" extension in my usecase but here I uploaded ".txt" because I couldn't upload the ".key" file here.
Could you please help letting me know what should be the required key format or how to proceed with this key file?
Attachments
priv.txt
(2.31 KiB) Downloaded 960 times

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: mbedtls CSR in ESP32

Postby ESP_Angus » Mon Sep 24, 2018 11:42 pm

mbedTLS will expect to see a key encoded in the standard PEM or DER formats. Docs.

If you want to parse a key from its raw numbers like this, you can technically do it (all the information is there) but you'll need to write the parser yourself by reading each MPI number from the file.

Take a look at mbedtls_pk_write_key_pem() and mbedtls_pk_write_key_der() for the functions to write a key which has been generated by the ESP32 to a file. Or you can generate the key with openssl or mbedTLS on the host, and copy the file to the device.

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

Re: mbedtls CSR in ESP32

Postby 16aa00 » Tue Sep 25, 2018 2:49 am

Thank you ESP_Angus

I will try with the mbedtls_pk_write_key_pem() and mbedtls_pk_write_key_der() functions and check whether it is working or not.

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

Re: mbedtls CSR in ESP32

Postby 16aa00 » Tue Oct 02, 2018 5:18 am

Hi,

I generated the RSA keys using the following code

Code: Select all

mbedtls_rsa_gen_key( mbedtls_pk_rsa( key ), mbedtls_ctr_drbg_random, &ctr_drbg, 1024, 65537 );
Here "key" is the mbedtls_pk_context and "ctr_drbg" is mbedtls_ctr_drbg_context (https://github.com/ARMmbed/mbedtls/blob ... /gen_key.c)

Now to generate the CSR (following https://github.com/ARMmbed/mbedtls/blob ... cert_req.c), I did the following (According to me, I need not load the key again in mbedtls pk context because I already generated key above using the pk context, so I skipped the loading of key to pk context part):-

Code: Select all

mbedtls_x509write_csr_set_md_alg( &req, MBEDTLS_MD_SHA256 );
if( opt.key_usage )
      mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage );

   if( opt.ns_cert_type )
      mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type );
   /*
   * 0. Seed the PRNG
   */
  mbedtls_printf( "  . Seeding the random number generator..." );

  mbedtls_entropy_init( &entropy );
  if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                             (const unsigned char *) pers,
                             strlen( pers ) ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d", ret );
      return;
  }

  mbedtls_printf( " ok\n" );
  

  /*
   * 1.0. Check the subject name for validity
   */
  mbedtls_printf( "  . Checking subject name..." );

  if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt1.subject_name ) ) != 0 )
  {
      mbedtls_printf( " failed\n  !  mbedtls_x509write_csr_set_subject_name returned %d", ret );
      return;
  }
  
  mbedtls_x509write_csr_set_key( &req, &key );
  
  /*
   * 1.2. Writing the request
   */

  mbedtls_printf( "  . Writing the certificate request ..." );
  unsigned char output_buf[4096];
  
  memset(output_buf,0,sizeof(output_buf));
  
  if((ret = mbedtls_x509write_csr_pem(&req, output_buf, 4096, NULL, &ctr_drbg))<0){
    Serial.println("Writing csr in PEM format failed with exit code "+ ret);
    return;
  }
When I run this, the following error occurs:
Screenshot from 2018-10-02 06-54-09.png
Screenshot from 2018-10-02 06-54-09.png (96.23 KiB) Viewed 14055 times
After comment "mbedtls_x509write_csr_pem" part, everything runs fine.
Could you please help me?

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: mbedtls CSR in ESP32

Postby ESP_Angus » Tue Oct 02, 2018 5:22 am

"Stack canary watchpoint" in loopTask means that loopTask overflowed its stack.

I think recent ESP-IDF versions have a more meaningful message here, are you using an older version?

Increase the size of the loopTask stack in xTaskCreate(), and this crash will go away.

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

Re: mbedtls CSR in ESP32

Postby 16aa00 » Tue Oct 02, 2018 1:45 pm

ESP-IDF version is v3.2-dev.
Would you please provide any link on how to Increase the size of the loopTask stack in xTaskCreate() ?

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: mbedtls CSR in ESP32

Postby ESP_Angus » Wed Oct 03, 2018 6:29 am

I think the only way to do this is by editing the Arduino core code. Change the 8192 to a larger number, here:
https://github.com/espressif/arduino-es ... in.cpp#L24

Alternatively, call xTaskCreate() or xTaskCreatePinnedToCore() in your own code to create a new task with a bigger stack size.

16aa00
Posts: 11
Joined: Tue Sep 04, 2018 12:03 pm

Re: mbedtls CSR in ESP32

Postby 16aa00 » Mon Oct 08, 2018 5:06 am

Hi ESP_Angus,

Thanks for the solution. But, I am still not able to increase the loopTask stack size. I am not able where to find this Arduino core code to edit and also I am not sure how to call xTaskCreate() or xTaskCreatePinnedToCore().
Could you please be more specific how to increase to stack size of loopTask?

Thank you

Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot] and 71 guests