Skip to main content
KBhon.1
Associate II
January 3, 2023
Question

Adding STSAFE with mbedTLS client for IoT work

  • January 3, 2023
  • 19 replies
  • 17906 views

Hello all,

I am working on creating a secure IoT device. The device is configured as MQTT client which will be sending sensors data to the sever over MQTT. I have implemented encryption using mbed-TLS where I confirm server's authenticity with server CA certificate. 

Now I wish to implement 2 way authentication where I need to send client certificate to the server for verifying client authenticity by server.

I see it is possible with the help of mbed-TLS but we need to provide private key of the client to mbedTLS which is not possible since we cannot extract private key out of STSAFE. 

I have been searching on this from almost a month and I have not been able to find a direct example on implementing this.

Also, the STSAFE examples are not clear about implementing this with mbedTLS.

I am in search of something that links stsfae with mbedTLS for client authentication.

Can anyone please guide me how to implement this?

19 replies

ST Employee
February 6, 2023

Hi @Community member​ ,

in the code provided, you have the clientcert and clientkey structure that are initialized as follow :

 // Init MbedTLS structure for client certificate and client key 

 mbedtls_x509_crt_init( &clientcert );

 mbedtls_pk_init( &clientkey );

 // Code example to fetch a certificate from STSAFE-A memory (warning if certificate size is more than 507 bytes, the read operation shall be split)

 printf("Get Stsafe Certificate : ");

 fflush(stdout);

 ret = STSAFE_GetCertificate(&stsafe_handle, 0, cert_buf, &cert_buf_size);

 if (ret < 0)

 {

  printf( " failed " ENDL " ! read certificate from STSAFE-A memory -0x%x"ENDL ENDL, -ret );

  goto exit;

 }

 printf("OK" ENDL);

 // parse the STSAFE-A certificate for mbedtls_x509_crt structure 

 // this certificate shall be used in SSL context in mbedtls_ssl_conf_own_cert()

 printf("Parse Stsafe Certificate in mbedtls_x509_crt structure : ");

 fflush(stdout);

 ret = mbedtls_x509_crt_parse( &clientcert, (const unsigned char *)cert_buf, cert_buf_size);

 if( ret < 0 )

 {

  printf( " failed"ENDL" ! mbedtls_x509_crt_parse returned -0x%x" ENDL ENDL, -ret );

  goto exit;

 }

 printf( " OK" ENDL );

 // clientkey structure hack to redirect all signature operation to STSAFE-A signature feature

 // the STSAFE_GetMbedPK_ECDSAInfo() will use the STSAFE-A private key slot 0 by default

 printf("Set STSAFE-A pk_info structure to client key : ");

 fflush(stdout);

 clientkey.pk_info = STSAFE_GetMbedPK_ECDSAInfo(&stsafe_handle);

 printf("OK"ENDL);

after this init, both clientcert and clientkey are ready to use in the mbedtls_ssl_conf_own_cert() function.

The principle here is update the clientkey structure to redirect the sign feature to STSAFE-A wrapper in that case, you don't need to load an actual private key, only init the structure and the ssl context will be able to use it.

Best Regards,

Benjamin

KBhon.1
KBhon.1Author
Associate II
February 6, 2023

@Benjamin BARATTE​ ,

Wow, That's great!

I never knew you would make it so simple. :)

I will test this out with my local mosquitto server soon and will update you here.

Thank You very much for your help so far!

I really appreciate it.

Have a good day!

Regards,

Krunal

ST Employee
February 6, 2023

Hi @Community member​ ,

if Mosquitto does not support ECDSA, you can make a test with openssl server with the following command :

/usr/bin/openssl s_server -accept 4433 -Verify 1 -cert server.crt -key server.key -CAfile client_CA.crt -www -msg  -verify_return_error  -debug -cipher ECDHE-ECDSA-AES256-GCM-SHA384

you will need to generate a server.key and server.crt and make sure you have the CA that sign your server certificate in your device.

For le client_CA.crt, if you use the STSAFE-A certificate then you can use the following CA certificate

Best Regards,

Benjamin

KBhon.1
KBhon.1Author
Associate II
February 6, 2023

@Benjamin BARATTE​ ,

Yes, I have mosquitto's CA certificate to test mosquitto server, and I had been planning to use ST CA certificate provided on the website as client's CA certificate.

Thanks for providing additional info. I will surely try openssl if I can't make mosquitto run.

Will update you here soon.

Thanks :)

Regards,

Krunal

KBhon.1
KBhon.1Author
Associate II
February 20, 2023

@Benjamin BARATTE​ 

Sorry for the delay in replying as I wanted to make sure I tried everything.

Also, Setting up local mosquitto server with SAN (Subject Alternative name) took time.

Finally I managed to setup local mosquitto server. I tested it using MQTT Explorer by providing client, server, CA certificates and it worked. This worked with/without client authentication using MQTT Explorer.

Later I tried running our code (first without client authentication), but it failed to connect.

Next, I tried using your provided command for openSSL, this time also without client authentication, but i am still getting that "no shred ciphers"

Here I have attached errors debug for device and openssl.

From this it seems I am still doing something wrong with the mbedtls configuration.

I have following enabled for medtls_config.h file:

MBEDTLS_ECP_DP_SECP256R1_ENABLED,

MBEDTLS_ECP_DP_SECP384R1_ENABLED

MBEDTLS_ECP_DP_BP256R1_ENABLED,

MBEDTLS_ECP_DP_BP384R1_ENABLED

MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED,

MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED

MBEDTLS_ECDSA_C

MBEDTLS_ECDH_C

  • disabled MBEDTLS_KEY_EXCHANGE_RSA_ENABLED

0693W00000aHAwYQAW.png 

ST Employee
February 27, 2023

Hi @Community member​ ,

I see that the server use AES256 and SHA384 while the client does not propose such ciphersuite.

Did you activate the MBEDTLS_SHA384_C and MBEDTLS_SHA512_C ?

I see in the MbedTLS definition that the AES256 is only linked to the SHA384.

Therefore if you activate the SHA384 (and SHA512) you should provide more ciphersuite and be able to match server preferences.

Best Regards,

Benjamin

KBhon.1
KBhon.1Author
Associate II
March 4, 2023

Hello @Benjamin BARATTE​ ,

Thanks for your support so far.

You were right, I had missed to enable MBEDTLS_SHA384_C.

Apart from this, my keys for broker and CA were generated using RSA which I later found that I need to generate ECP certificates and keys for broker and CA too.

I am working on it and have gone further.

Now I generated broker, CA, and client certificates using SECP384R1 and used cipher ECDHE-ECDSA-AES256-GCM-SHA384. So when I provided my generated client certificate, the handshake worked.

Next I incorporated your provided example and tried to use slot0 of stsafe. I noticed slot0 uses NIST-256 so I regenerated my broker, CA certificates using NIST-256 (prime256v1).

The handshake went much further and mbedtls_ecdh_gen_public() function was called from your provided file. However it fails when StSafeA_GenerateKeyPair() is called within this function. Following is the line that returns error "STSAFEA_INVALID_PARAMETER".

status_code = StSafeA_GenerateKeyPair(g_se_handle, STSAFEA_KEY_SLOT_EPHEMERAL, 0x0001U, 1U, 0, curve, size, &reppoint, &x, &y, STSAFEA_MAC_NONE);

On further debugging, I saw it fails at "IS_STSAFEA_HANDLER_VALID_PTR(pStSafeA)" within StSafeA_GenerateKeyPair(), however, I could see in debug it has a valid pointer.

Apart from these points, I am also facing problem with GenerateCSRFromPublicKey() function in your provided example file. Initially it was working, but now it returns error ret = -1. this is the code line that fails.

ret = GenerateCSRFromPublicKey(&stsafe_handle, COUNTRY_STR, ORG_STR, CN_KEY_1, KEY_1_CURVE, X, Y, display_buffer, &csr_size);

I feel now I am very close to getting STSAFE working with mbedTLS, thanks to your support. Waiting for your reply.

Thank You.

KBhon.1
KBhon.1Author
Associate II
March 22, 2023

Hello @Benjamin BARATTE​ ,

Good Day!

Thank You for your continued support!

Now I am trying to use slot1 for generating my keys and then CSR which I get signed by my CA.

With your provided example, the keys and generated CSR for slot1 are always changing and I am unable to use slot1 for client authentication.

Is it possible to save the slot1 generated key into slot1 itself? Also can you please share how to upload signed certificate for slot1 to stsfae?

Can you please share an example code for both of these?

Thank You.

ST Employee
March 22, 2023

Hi @Community member​,

The code example presents a one time operation which is key generation and CSR generation.

The private key is store in the slot1 and the public key is used to generate the CSR.

You don't need to run the code at every boot for sure.

Once you have the Certificate from your PKI, you can store it in STSAFE-A memory region (for instance region 1) using StSafeA_Update function or in MCU flash memory.

For your TLS handshake, you need to modify the pk.pk_info with STSAFE_GetMbedPK_ECDSAInfo_1 function.

Best Regards,

Benjamin

KBhon.1
KBhon.1Author
Associate II
March 22, 2023

Hi @Benjamin BARATTE​ 

Thank you for the immediate response.

I tried your suggested method and didn't generate key pair and CSR for slot1.

I hardcoded certificate in the flash.

Passed STSAFE_GetMbedPK_ECDSAInfo_1 to pk.pk_info.

The handshake went ahead and gave error when StSafeA_GenerateSignature was called from stsafe_sign_wrap_1().

I have attached the debug session image for the reference.

The highlighted line 1382 returns "STSAFEA_INVALID_RESP_LENGTH", upon more inspection into that function, I see the pDestLVBuffer->Length = 48 but ExpectedLen = 0;

Please suggest.

Thank You.

0693W00000aJUGBQA4.png 

@Benjamin BARATTE​ 

Edit: I figured out g_key_1_size was initialized to 0 which should have been 48 as I generated SECP384 key. Now the handshake worked.

Going to try out saving the certificate into the STSAFE flash and will update you soon.

Thank You.:folded_hands:

ST Employee
March 22, 2023

Hi @Community member​,

Effectively, the g_key_1_size shall be kept by the application in order to get the correct key size of the private slot 1.

As the key is generated by the application, the application is best place to reset the global variable at each start up without regenerating a key.

Best Regards,

Benjamin

KBhon.1
KBhon.1Author
Associate II
September 20, 2023

Hi @Benjamin BARATTE ,

With your help we had been successful in implementing STSAFE authentication in our project. Thank you very much for your help so far.

Now we are facing a new issue in this, we generated CSR from key pair of STSAFE. Got it signed with our own CA. Now we want to confirm that the signed certificate actually belongs to the STSAFE key. We wanted to check if the certificate with the controller has the same public key on it that belongs to its private key. We could do that successfully for keys generated with mbedTLS, but saw it failing with STSAFE keys. We tried using function "mbedtls_pk_check_pair".

We checked on mbedTLS git page and found following issue:
https://github.com/Mbed-TLS/mbedtls/issues/3903
They say, this may not be possible for secure elements.

Could you please suggest why this would be failing and how to solve this?
Thank You.

ST Employee
December 11, 2023

Hi @KBhon.1,

As the private key inside the STSAFE-A is not accessible, you can't use the mbedtls_pk_check_pair function.

 

The only way to check that the public key is related to the STSAFE-A private key is to either check the public key value from the certificate match the public key you have put in your CSR.

For that, you need to same the public key on your side (you can use a memory region of the STSAFE-A to store it)

 

Or as a signature request to the STSAFE-A and use the public key in the certificate to verify the generated signature.

If the signature is verified then the public key belong to the private key.

 

Best Regards,

 

Benjamin

Associate II
December 10, 2024

Hi @Benjamin BARATTE,

I've tried to use the example code that you have so kindly provided here in this topic with mbedTLS version , but I think that unfortunately there is a small issue with this version. This is that the pk_wrap.h file, where the precious definition of the struct mbedtls_pk_info_t is included, is not any longer available to be included at the include directory. Therefore we can't declare our custom mbedtls_pk_info_t  structures.

Are you aware of a workaround for this challenge?