This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

mbedtls RSA trouble, mbedtls_rsa_import/mbedtls_rsa_complete fails

Hi,

Working on RSA encryption, I'm trying to build an RSA context from just the P, Q and E part of the key (as per https://tls.mbed.org/kb/development/how-to-fill-rsa-context-from-n-e-p-and-q)

I have this sequence working on a windows machine, using the latest mbedtls release on visual studio 2019.

mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V15, 0);
ret = mbedtls_rsa_import(&ctx, NULL, &P, &Q, NULL, &E);
if (ret != 0)
{
    mbedtls_printf(" failed\n  ! mbedtls_rsa_import returned %d\n\n", ret);
}
if ((ret = mbedtls_rsa_complete(&ctx)) != 0)
{
     mbedtls_printf(" failed\n  ! mbedtls_rsa_complete returned %d\n\n", ret);
}

When doing the same thing on a nrf52840 board, the mbedtls_rsa_complete call fails with errorcode -16512, 'RSA - Bad input parameters to function'.

When I compare the RSA context structure after the mbedtls_rsa_import call, the contents are identical (nrf vs windows), using the same P/Q/E input arrays.

So, this might be a long shot here, but I'm not sure where to look now. The mbedtls code is rather hard to follow, sofar I have not been able to tell why the function fails. Both machines are little endian, so that shouldn't be it, right? I've tried setting a larger heap (CONFIG_MBEDTLS_HEAP_SIZE=2048), but that did not make any difference either.

Any pointers?

  • Hi Didrik,

    Spend the day doing some testing. When I do the same entropy-trick (using the local f_rng function instead of mbedtls_entropy_func) stuff starts to work.

    BUT, if I'm correct, I'm not using the cryptocell hardware. What do I need to do to get that working?

    I've created a test-project, just doing the encryption, nothing else. I need AES-128 and RSA-1024. To get AES working, I need CONFIG_OBERON_BACKEND=y, otherwise the output is all zero's.

    For RSA, i need to set CONFIG_CC3XX_BACKEND=n, or mbedtls_rsa_complete() fails with an input error.

    If you could take a look at my code, i've uploaded it here

    and the included testdata here

    prj.conf is here

    (think i don't have the option of uploading stuff to the ticket, like you did?)

  • Hi Didrik and colleagues,

    Best wishes for the new year Slight smile

    Just making sure my ticket won't be forgotten over the holidays.. ;)

  • Hi, and happy new year to you too.

     

    basvkesteren said:
    (think i don't have the option of uploading stuff to the ticket, like you did?)

     You should be able to, although not every file type is allowed, so e.g., your prj.conf must either be renamed to something else than *.conf, or it must be in a zipped folder.

    You can find the option to upload files here:

    I've looked at your code, and you are correct that it doesn't use the cryptocell for the RSA encryption.

    I believe the cryptocell is still used to get random numbers, but it is definitely used if you change your f_rng() to this:

    #include <drivers/entropy.h>
    
    static int f_rng(void *ctx, unsigned char *buf, size_t len)   
        const struct device *dev = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL);
        
        static int first = 1;
        if (first) {
            printk("Name of entropy device: %s\n", dev->name);
            first = 0;
        }
        
    	if (!dev) {
    		printk("error: no entropy device\n");
    		return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
    	}
    	int err = entropy_get_entropy(dev, buf, len);
    	if (err) {
    		printk("Failed to get entropy\n");
    		return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
    	}
    
    	return 0;
    }

    I would also change your call to mbedtls_rsa_private to use mbedtls_ctr_drbg_random instead of f_rng.

    Unfortunately, I have not yet been able to get the cryptocell to perform the actual RSA encryption (though it should be possible). I will ask our developers if they can see what we are doing wrong.

  • Hi Didrik,

    Thanks for the reply! About that upload, dunno how I've missed that button... A well.

    But, any word from the developers?

    Since I've uploaded my initial testcode I've been tweaking and fixing the mbedtls code; it's working stable now, but rather slow (especially the RSA calls). Would like to fix that Slight smile

  • Hi, and sorry for the slow response.

    The reason for why it fails when using the cryptocell is because the library doesn't calculate N based on P and Q.

    However, if you calculate N and provide it to the library, it will work.

    We will also add this missing detail in future versions of the crypto libraries.

    This is the code snippet that should have been in the crypto library:

       if( !have_N && have_P && have_Q )
        {
            if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
                                             &ctx->Q ) ) != 0 )
            {
                return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
            }
    
            ctx->len = mbedtls_mpi_size( &ctx->N );
        }

Related