Arm Mbed and Pelion Device Management support forum

Problem with mbedtls_rsa_import_raw while mbedtls_rsa_import is working fine

I am creating a demo program to explain how to import OpenSSL generated Private key, Signing message, extracting public part and Independently Verifying a messege digest using RSA.N, RSA.E, Signature, Digest.

While am trying to pass public parameters as char, I am getting following error.
failed! mbedtls_rsa_complete: -4080
WHile passing mbedtls_mpi* the same program is working fine. Any help would be appreciated. [snippet given below]

Thanks,

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <mbedtls/md.h>
#include <mbedtls/pk.h>
#include <mbedtls/rsa.h>

typedef struct RsaPublic
{
   mbedtls_mpi N;
   mbedtls_mpi E;
}RsaPublic_t;

typedef struct Signature
{
   uint8_t Signature[MBEDTLS_MPI_MAX_SIZE];
   size_t SignatureLength;
   uint8_t Digest[MBEDTLS_MD_MAX_SIZE];
   size_t DigestLength;
   mbedtls_pk_context PK;
   RsaPublic_t Public;
}Signature_t;

void SignatureInit( Signature_t *CTX )
{
   if( NULL == CTX )
   {
	  return;
   }

   memset( CTX, 0x00, sizeof(Signature_t) );

   mbedtls_pk_init( &CTX->PK );

   mbedtls_mpi_init( &CTX->Public.N );
   mbedtls_mpi_init( &CTX->Public.E );
}

int HexDump( uint8_t *Stream, size_t StreamLength )
{
   int i;
   for( i=0; i < StreamLength; i++ )
   {
	  printf("%02X", 0xff & Stream[i]);
   }
   printf("\r\n");

   return i;
}

int ReadKeyFile( Signature_t *CTX, uint8_t *FileName, uint8_t *Password )
{
   return ( mbedtls_pk_parse_keyfile( &CTX->PK, FileName, Password ) );
}

int GetFileDigest( Signature_t *CTX, uint8_t *FileName )
{
   CTX->DigestLength = 32;
   return( mbedtls_md_file( mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ),
							  FileName, CTX->Digest ) );
}

int SignDigest( Signature_t *CTX )
{
   mbedtls_rsa_context *rsa = mbedtls_pk_rsa(CTX->PK);
   CTX->SignatureLength = rsa->len;
   return( mbedtls_rsa_pkcs1_sign( rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
								   MBEDTLS_MD_MAX_SIZE, CTX->Digest, CTX->Signature ) );
}

int ExportPublic( Signature_t *CTX )
{
   mbedtls_rsa_context *rsa = mbedtls_pk_rsa(CTX->PK);
   return( mbedtls_rsa_export( rsa, &CTX->Public.N, NULL, NULL, NULL, &CTX->Public.E ) );
}

int VerifyOnly( uint8_t *Digest, size_t DigestLength,
				uint8_t *Signature, size_t SignatureLength,
//		uint8_t *N, size_t N_len, uint8_t *E, size_t E_len )
// Problem while using above line
		mbedtls_mpi *N, mbedtls_mpi *E )
{
   int ret = EXIT_SUCCESS;

   /* Verify uses it's RSA Context */
   mbedtls_rsa_context rsa;

   /* Initialize RSA Context */
   mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );

   /* Import RSA Publc Parameters */
   //if( ret = mbedtls_rsa_import_raw( &rsa, N, N_len, NULL, 0, NULL, 0, NULL, 0, E, E_len ) )
   // Problem while using above line
   if( ret = mbedtls_rsa_import( &rsa, N, NULL, NULL, NULL, E ) )
   {
	  printf( "failed! mbedtls_rsa_import_raw: -%04x", -ret );
	  return (ret);
   }

   if( ret = mbedtls_rsa_complete( &rsa ) )
   {
	  printf( "failed! mbedtls_rsa_complete: -%04x", -ret );
	  return (ret);
   }

   return( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
									   32, Digest, Signature ) );
}

int main()
{
   int ret = EXIT_SUCCESS;

   Signature_t S1;

   SignatureInit( &S1 );

   // Can ready any PEM formatted RSA Key file here
   //if( ret = ReadKeyFile( &S1, "private.key", NULL ) )
   if( ret = ReadKeyFile( &S1, "p.k", NULL ) )
   {
	  printf("... failed! ReadKeyFile -%04x", -ret);
	  return ret;      
   }

   if( ret = GetFileDigest( &S1, "Message.txt" ) )
   {
	  printf("... failed! DigestFile -%04x", -ret);
	  return ret;
   }
   printf("Message Digest:\r\n");
   HexDump( S1.Digest, MBEDTLS_MD_MAX_SIZE/2 );

   if( ret = SignDigest( &S1 ) )
   {
	  printf("... failed! ReadMsgFile -%04x", -ret);
	  return ret;
   }
   printf("Signature:\r\n");
   HexDump( S1.Signature, S1.SignatureLength );

   if( ret = ExportPublic( &S1 ) )
   {
	  printf("... failed! ExportPublic -%04x", -ret);
	  return ret;      
   }
   mbedtls_mpi_write_file( "N:", &S1.Public.N, 16, NULL );
   mbedtls_mpi_write_file( "E:", &S1.Public.E, 16, NULL );

   uint8_t _N[1024]; size_t _N_len;
   uint8_t _E[1024]; size_t _E_len;

   mbedtls_mpi_write_string( &S1.Public.N, 16, _N, 1024, &_N_len );
   mbedtls_mpi_write_string( &S1.Public.E, 16, _E, 1024, &_E_len );

   printf("Independent Verification Begin ");
   if( ret = VerifyOnly( S1.Digest, S1.DigestLength,
						 S1.Signature, S1.SignatureLength,
						 &S1.Public.N, &S1.Public.E ) )
//                         _N, _N_len, _E, _E_len ) )
   {
	  printf("... failed! VerifyOnly -%04x", -ret);
	  return ret;
   }
   printf("Done!\r\n");

   return(ret);
}

Hi @gopi219
The reason you are getting this faiolure, is because _N and E are *string representations of the data, however mbedtls_rsa_import_raw()` should get these parameters as raw big-endian binary format

The failure happens, because the ASCII value of the string you are giving is not the real N and E

Regards,
Mbed TLS Support
Ron