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?

Parents
  • basvkesteren said:
    Because I don't really have a clear picture about how and when the whole nrfxlib crypto stuff comes into play, the documentation (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrfxlib/crypto/README.html) is sort of useless; a changelog and an api-list really doesn't do...

     It is not meant that you should use the crypto libraries directly, instead, you should use the Nordic Security Module: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrfxlib/nrf_security/README.html

    I have also made a very small sample that seems to be working correctly, though I had to use Zephyr's sys_csrand_get() instead of mbedTLS's hardware_poll():

    mbedtls_rsa_import.zip

  • 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, 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 );
        }

  • Hi Didrik,

    Thanks for the response. So, do I understand it right that this missing functionality will be added to a future NCS release? Looks to me the crypto-library is binary only, I can't modify it myself, right?

    Also, I did a quick test this morning. In the following code the test_RSA_N/P/Q/E contain a valid RSA key. This sequence works with CONFIG_CC3XX_BACKEND=n, but fails with CONFIG_CC3XX_BACKEND=y (I get a 'mbedtls_rsa_complete failed: -16512' printout).

    What am I missing? I'm using NCS 1.4.0

        LOG_DBG("RSA import, again:");
        mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
        if((r = mbedtls_rsa_import_raw(&rsa, test_RSA_N, sizeof(test_RSA_N),
                                             test_RSA_P, sizeof(test_RSA_P), 
                                             test_RSA_Q, sizeof(test_RSA_Q),
                                             NULL, 0, /* D */
                                             test_RSA_E, sizeof(test_RSA_E)))) {
            mbedtls_strerror(r, errbuf, sizeof(errbuf));
            LOG_DBG("mbedtls_rsa_import_raw failed: %d (%s)", r, errbuf);
        }
        LOG_DBG("ok");
    
        LOG_DBG("mbedtls_rsa_complete");
        if((r = mbedtls_rsa_complete(&rsa))) {
            mbedtls_strerror(r, errbuf, sizeof(errbuf));
            LOG_DBG("mbedtls_rsa_complete failed: %d (%s)\n", r, errbuf);
        }
        LOG_DBG("ok");

  • Hi, and sorry for the late reply.

    Since my last comment, the developers has found even more problems with the library.

    It seems like you at least also have to provide E, although that is unpractical for the application.

    However, I have been promised that a Pull Request with an updated version of the library will be available within the next few days.

    Sorry for the inconvenience, and the time this is taking.

    Best regards,

    Didrik

Reply
  • Hi, and sorry for the late reply.

    Since my last comment, the developers has found even more problems with the library.

    It seems like you at least also have to provide E, although that is unpractical for the application.

    However, I have been promised that a Pull Request with an updated version of the library will be available within the next few days.

    Sorry for the inconvenience, and the time this is taking.

    Best regards,

    Didrik

Children
Related