Mbed forum

After parsing RSA2048 private key (generated using OpenSSL) QP coefficient doesn't match with original one


(Alex Pimenov) #1

I’m using mbedtls_pk_parse_key(…) function to parse RSA private key in DER format. This function returns success, but if use resulting rsa context to decrypt a buffer with mbedtls_rsa_pkcs1_decrypt() function - it always returns unknown error(8680).
After some debugging I noticed that following private key components : modulus, publicExponent, privateExponent, prime1, prime2 match with data that stored in DER formatted key, but exponent1, exponent2 and coefficient do not match the corresponding components in DER formatted key.

I was using this his private/public key pair for a while with WolfSSL library on Kinetis K64 MCU and parsing DER formatted RSA public or private keys never been an issue, but it doesn’t look like it’s working correctly with mbedTLS.


(Ron Eldor) #2

@apimenov
Thank you for your information.
Is the error code you are receiving in hex or decimal format?
What is the private key format you are using(e.g. PKCS #8)?
Could you add a code example which reproduces this issue?
Regards,
Mbed TLS Team member
Ron


(Alex Pimenov) #3

Private key format is in PKSC1 format.

“UNKNOWN ERROR CODE (8680)” this is what mbedtls_strerror() function prints out. If I step through mbedtls_rsa_private(…) function with the debugger, I can see it fails here:
if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
{
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
goto cleanup;
}

After double checking I can confirm that only QP coefficient doesn’t match with original value after parsing, DP and DQ are being parsed correctly.
I also noticed that N, E, D, P, and Q are actually being retrieved from PKSC1 private key, but QP, DP, DQ are computed based on D, P and Q. Seems like DP and DQ are being computed correctly, but QP is not. So if I overwrite QP with the value that is retrieved from PKSC1 private key - private decryption starts working as expected.


(Alex Pimenov) #4

Here is the function. If PRIV_KEY_WORKAROUND is defined decryption is working correctly, if it’s not defined
decryption is failing. u_bin[] array contains actual QP data from DER formatted key.

int rsa_private_decrypt(const uint8_t* der_data, size_t der_data_size, const uint8_t* in, size_t inLen, uint8_t* out, size_t outLen)
{

int ret;
size_t i;
mbedtls_pk_context key;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;

mbedtls_pk_init( &key );
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );

ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
                                    &entropy, (const unsigned char *) pers,
                                    strlen( pers ) );
 if(ret != 0) {     
    goto exit;
}

ret = mbedtls_pk_parse_key(&key, der_data, der_data_size, NULL, 0);
if(ret != 0) {     
    goto exit;
}
mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key );

#if defined (PRIV_KEY_WORKAROUND)
memcpy((uint8_t )rsa->QP.p, u_bin, sizeof(u_bin));
#endif
i = 0;
ret = mbedtls_rsa_pkcs1_decrypt( rsa, /mbedtls_ctr_drbg_random/ NULL,
/
&ctr_drbg*/ NULL, MBEDTLS_RSA_PRIVATE, &i,
in, out, outLen );

 if(ret != 0) {   
    char error[100];
    mbedtls_strerror(ret, error, sizeof(error) );
    PRINTF("%s", error);  
    goto exit;
}

exit:
mbedtls_pk_free(&key);
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
return ret;
}


(Ron Eldor) #5

@apimenov
Thank you for your information and for sharing your code example.

I am assuming you are using CRT mode, and that you have MBEDTLS_RSA_NO_CRT undefined.
According to RFC 3447 , QP coefficient is not part of the private key format, so I am having trouble understanding where you got the value from.
Could you please also share the command you did to generate the key? Does this reproduce with every key you generate or only one specific key? I am trying to understand if this is a corner case.
Regards,
Mbed TLS Team member
Ron


(Alex Pimenov) #6

I figured it out. Because FreeRTOS doesn’t provide calloc(…) function ( it only provides malloc()) when internal heap implementation is used (heap_4.c). I had to implement calloc () based on the FreeRTOS pvPortMalloc(), but I did not zeroize memory chunk it allocated and this was causing issues described above.