mbedtls/tests/suites/test_suite_rsa.function
Hanno Becker c77ab892e5 Add tests for rsa_import, rsa_import_raw and rsa_complete
This commit adds numerous tests for the new library functions mbedtls_rsa_import
and mbedtls_rsa_import_raw in conjunction with mbedtls_rsa_complete for
importing and completing core sets of core RSA parameters (N,P,Q,D,E) into an
RSA context, with the importing accepting either MPI's or raw big endian
buffers.

Each test is determined by the following parameters:
1) Set of parameters provided
   We're testing full sets (N,P,Q,D,E), partial sets (N,-,-,D,E) and (N,P,Q,-,E)
   that are sufficient to generate missing parameters, and the partial and
   insufficient set (N, -, Q, -, E).
2) Simultaenous or successive importing
   The functions rsa_import and rsa_import_raw accept importing parameters at
   once or one after another. We test both.
3) Sanity of parameters
2017-08-23 15:02:57 +01:00

1014 lines
35 KiB
Text

/* BEGIN_HEADER */
#include "mbedtls/rsa.h"
#include "mbedtls/md2.h"
#include "mbedtls/md4.h"
#include "mbedtls/md5.h"
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_RSA_C:MBEDTLS_BIGNUM_C:MBEDTLS_GENPRIME
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
void mbedtls_rsa_pkcs1_sign( char *message_hex_string, int padding_mode, int digest,
int mod, int radix_P, char *input_P, int radix_Q,
char *input_Q, int radix_N, char *input_N, int radix_E,
char *input_E, char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char hash_result[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx;
mbedtls_mpi P1, Q1, H, G;
int msg_len;
rnd_pseudo_info rnd_info;
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( hash_result, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &P1, &ctx.P, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &Q1, &ctx.Q, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_gcd( &G, &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.D , &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DP, &ctx.D, &P1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DQ, &ctx.D, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.QP, &ctx.Q, &ctx.P ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
msg_len = unhexify( message_str, message_hex_string );
if( mbedtls_md_info_from_type( digest ) != NULL )
TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str, msg_len, hash_result ) == 0 );
TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE, digest, 0, hash_result, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
exit:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_pkcs1_verify( char *message_hex_string, int padding_mode, int digest,
int mod, int radix_N, char *input_N, int radix_E,
char *input_E, char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char hash_result[1000];
unsigned char result_str[1000];
mbedtls_rsa_context ctx;
int msg_len;
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( hash_result, 0x00, 1000 );
memset( result_str, 0x00, 1000 );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
msg_len = unhexify( message_str, message_hex_string );
unhexify( result_str, result_hex_str );
if( mbedtls_md_info_from_type( digest ) != NULL )
TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str, msg_len, hash_result ) == 0 );
TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, digest, 0, hash_result, result_str ) == result );
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void rsa_pkcs1_sign_raw( char *message_hex_string, char *hash_result_string,
int padding_mode, int mod, int radix_P, char *input_P,
int radix_Q, char *input_Q, int radix_N,
char *input_N, int radix_E, char *input_E,
char *result_hex_str )
{
unsigned char message_str[1000];
unsigned char hash_result[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx;
mbedtls_mpi P1, Q1, H, G;
int hash_len;
rnd_pseudo_info rnd_info;
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( hash_result, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &P1, &ctx.P, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &Q1, &ctx.Q, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_gcd( &G, &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.D , &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DP, &ctx.D, &P1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DQ, &ctx.D, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.QP, &ctx.Q, &ctx.P ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
unhexify( message_str, message_hex_string );
hash_len = unhexify( hash_result, hash_result_string );
TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &rnd_pseudo_rand, &rnd_info,
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_NONE,
hash_len, hash_result, output ) == 0 );
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
/* For PKCS#1 v1.5, there is an alternative way to generate signatures */
if( padding_mode == MBEDTLS_RSA_PKCS_V15 )
{
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
TEST_ASSERT( mbedtls_rsa_rsaes_pkcs1_v15_encrypt( &ctx,
&rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE,
hash_len, hash_result, output ) == 0 );
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
exit:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void rsa_pkcs1_verify_raw( char *message_hex_string, char *hash_result_string,
int padding_mode, int mod, int radix_N,
char *input_N, int radix_E, char *input_E,
char *result_hex_str, int correct )
{
unsigned char message_str[1000];
unsigned char hash_result[1000];
unsigned char result_str[1000];
unsigned char output[1000];
mbedtls_rsa_context ctx;
size_t hash_len, olen;
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( hash_result, 0x00, 1000 );
memset( result_str, 0x00, 1000 );
memset( output, 0x00, sizeof( output ) );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
unhexify( message_str, message_hex_string );
hash_len = unhexify( hash_result, hash_result_string );
unhexify( result_str, result_hex_str );
TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, NULL, NULL,
MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_NONE,
hash_len, hash_result,
result_str ) == correct );
/* For PKCS#1 v1.5, there is an alternative way to verify signatures */
if( padding_mode == MBEDTLS_RSA_PKCS_V15 )
{
int ok;
TEST_ASSERT( mbedtls_rsa_rsaes_pkcs1_v15_decrypt( &ctx,
NULL, NULL, MBEDTLS_RSA_PUBLIC,
&olen, result_str, output, sizeof( output ) ) == 0 );
ok = olen == hash_len && memcmp( output, hash_result, olen ) == 0;
if( correct == 0 )
TEST_ASSERT( ok == 1 );
else
TEST_ASSERT( ok == 0 );
}
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_pkcs1_encrypt( char *message_hex_string, int padding_mode, int mod,
int radix_N, char *input_N, int radix_E, char *input_E,
char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx;
size_t msg_len;
rnd_pseudo_info rnd_info;
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
msg_len = unhexify( message_str, message_hex_string );
TEST_ASSERT( mbedtls_rsa_pkcs1_encrypt( &ctx, &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PUBLIC, msg_len, message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void rsa_pkcs1_encrypt_bad_rng( char *message_hex_string, int padding_mode,
int mod, int radix_N, char *input_N,
int radix_E, char *input_E,
char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx;
size_t msg_len;
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
msg_len = unhexify( message_str, message_hex_string );
TEST_ASSERT( mbedtls_rsa_pkcs1_encrypt( &ctx, &rnd_zero_rand, NULL, MBEDTLS_RSA_PUBLIC, msg_len, message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_pkcs1_decrypt( char *message_hex_string, int padding_mode, int mod,
int radix_P, char *input_P, int radix_Q, char *input_Q,
int radix_N, char *input_N, int radix_E, char *input_E,
int max_output, char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx;
mbedtls_mpi P1, Q1, H, G;
size_t output_len;
rnd_pseudo_info rnd_info;
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
mbedtls_rsa_init( &ctx, padding_mode, 0 );
memset( message_str, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &P1, &ctx.P, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &Q1, &ctx.Q, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_gcd( &G, &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.D , &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DP, &ctx.D, &P1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DQ, &ctx.D, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.QP, &ctx.Q, &ctx.P ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
unhexify( message_str, message_hex_string );
output_len = 0;
TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE, &output_len, message_str, output, max_output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strncasecmp( (char *) output_str, result_hex_str, strlen( result_hex_str ) ) == 0 );
}
exit:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_public( char *message_hex_string, int mod, int radix_N, char *input_N,
int radix_E, char *input_E, char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx, ctx2; /* Also test mbedtls_rsa_copy() while at it */
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
mbedtls_rsa_init( &ctx2, MBEDTLS_RSA_PKCS_V15, 0 );
memset( message_str, 0x00, 1000 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
unhexify( message_str, message_hex_string );
TEST_ASSERT( mbedtls_rsa_public( &ctx, message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
/* And now with the copy */
TEST_ASSERT( mbedtls_rsa_copy( &ctx2, &ctx ) == 0 );
/* clear the original to be sure */
mbedtls_rsa_free( &ctx );
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx2 ) == 0 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
TEST_ASSERT( mbedtls_rsa_public( &ctx2, message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx2.len );
TEST_ASSERT( strcasecmp( (char *) output_str, result_hex_str ) == 0 );
}
exit:
mbedtls_rsa_free( &ctx );
mbedtls_rsa_free( &ctx2 );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_private( char *message_hex_string, int mod, int radix_P, char *input_P,
int radix_Q, char *input_Q, int radix_N, char *input_N,
int radix_E, char *input_E, char *result_hex_str, int result )
{
unsigned char message_str[1000];
unsigned char output[1000];
unsigned char output_str[1000];
mbedtls_rsa_context ctx, ctx2; /* Also test mbedtls_rsa_copy() while at it */
mbedtls_mpi P1, Q1, H, G;
rnd_pseudo_info rnd_info;
int i;
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
mbedtls_rsa_init( &ctx2, MBEDTLS_RSA_PKCS_V15, 0 );
memset( message_str, 0x00, 1000 );
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
ctx.len = mod / 8;
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &P1, &ctx.P, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &Q1, &ctx.Q, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_gcd( &G, &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.D , &ctx.E, &H ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DP, &ctx.D, &P1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &ctx.DQ, &ctx.D, &Q1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_inv_mod( &ctx.QP, &ctx.Q, &ctx.P ) == 0 );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
unhexify( message_str, message_hex_string );
/* repeat three times to test updating of blinding values */
for( i = 0; i < 3; i++ )
{
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
TEST_ASSERT( mbedtls_rsa_private( &ctx, rnd_pseudo_rand, &rnd_info,
message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx.len );
TEST_ASSERT( strcasecmp( (char *) output_str,
result_hex_str ) == 0 );
}
}
/* And now one more time with the copy */
TEST_ASSERT( mbedtls_rsa_copy( &ctx2, &ctx ) == 0 );
/* clear the original to be sure */
mbedtls_rsa_free( &ctx );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx2 ) == 0 );
memset( output, 0x00, 1000 );
memset( output_str, 0x00, 1000 );
TEST_ASSERT( mbedtls_rsa_private( &ctx2, rnd_pseudo_rand, &rnd_info,
message_str, output ) == result );
if( result == 0 )
{
hexify( output_str, output, ctx2.len );
TEST_ASSERT( strcasecmp( (char *) output_str,
result_hex_str ) == 0 );
}
exit:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
mbedtls_rsa_free( &ctx ); mbedtls_rsa_free( &ctx2 );
}
/* END_CASE */
/* BEGIN_CASE */
void rsa_check_privkey_null()
{
mbedtls_rsa_context ctx;
memset( &ctx, 0x00, sizeof( mbedtls_rsa_context ) );
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_check_pubkey( int radix_N, char *input_N, int radix_E, char *input_E,
int result )
{
mbedtls_rsa_context ctx;
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
if( strlen( input_N ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
}
if( strlen( input_E ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
}
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == result );
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_check_privkey( int mod, int radix_P, char *input_P, int radix_Q,
char *input_Q, int radix_N, char *input_N,
int radix_E, char *input_E, int radix_D, char *input_D,
int radix_DP, char *input_DP, int radix_DQ,
char *input_DQ, int radix_QP, char *input_QP,
int result )
{
mbedtls_rsa_context ctx;
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
ctx.len = mod / 8;
if( strlen( input_P ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
}
if( strlen( input_Q ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
}
if( strlen( input_N ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
}
if( strlen( input_E ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
}
if( strlen( input_D ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.D, radix_D, input_D ) == 0 );
}
if( strlen( input_DP ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.DP, radix_DP, input_DP ) == 0 );
}
if( strlen( input_DQ ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.DQ, radix_DQ, input_DQ ) == 0 );
}
if( strlen( input_QP ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &ctx.QP, radix_QP, input_QP ) == 0 );
}
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == result );
exit:
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void rsa_check_pubpriv( int mod, int radix_Npub, char *input_Npub,
int radix_Epub, char *input_Epub,
int radix_P, char *input_P, int radix_Q,
char *input_Q, int radix_N, char *input_N,
int radix_E, char *input_E, int radix_D, char *input_D,
int radix_DP, char *input_DP, int radix_DQ,
char *input_DQ, int radix_QP, char *input_QP,
int result )
{
mbedtls_rsa_context pub, prv;
mbedtls_rsa_init( &pub, MBEDTLS_RSA_PKCS_V15, 0 );
mbedtls_rsa_init( &prv, MBEDTLS_RSA_PKCS_V15, 0 );
pub.len = mod / 8;
prv.len = mod / 8;
if( strlen( input_Npub ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &pub.N, radix_Npub, input_Npub ) == 0 );
}
if( strlen( input_Epub ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &pub.E, radix_Epub, input_Epub ) == 0 );
}
if( strlen( input_P ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.P, radix_P, input_P ) == 0 );
}
if( strlen( input_Q ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.Q, radix_Q, input_Q ) == 0 );
}
if( strlen( input_N ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.N, radix_N, input_N ) == 0 );
}
if( strlen( input_E ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.E, radix_E, input_E ) == 0 );
}
if( strlen( input_D ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.D, radix_D, input_D ) == 0 );
}
if( strlen( input_DP ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.DP, radix_DP, input_DP ) == 0 );
}
if( strlen( input_DQ ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.DQ, radix_DQ, input_DQ ) == 0 );
}
if( strlen( input_QP ) )
{
TEST_ASSERT( mbedtls_mpi_read_string( &prv.QP, radix_QP, input_QP ) == 0 );
}
TEST_ASSERT( mbedtls_rsa_check_pub_priv( &pub, &prv ) == result );
exit:
mbedtls_rsa_free( &pub );
mbedtls_rsa_free( &prv );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_CTR_DRBG_C:MBEDTLS_ENTROPY_C */
void mbedtls_rsa_gen_key( int nrbits, int exponent, int result)
{
mbedtls_rsa_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "test_suite_rsa";
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen( pers ) ) == 0 );
mbedtls_rsa_init( &ctx, 0, 0 );
TEST_ASSERT( mbedtls_rsa_gen_key( &ctx, mbedtls_ctr_drbg_random, &ctr_drbg, nrbits, exponent ) == result );
if( result == 0 )
{
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx.P, &ctx.Q ) > 0 );
}
exit:
mbedtls_rsa_free( &ctx );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_CTR_DRBG_C:MBEDTLS_ENTROPY_C */
void mbedtls_rsa_deduce_moduli( int radix_N, char *input_N,
int radix_D, char *input_D,
int radix_E, char *input_E,
int radix_P, char *output_P,
int radix_Q, char *output_Q,
int corrupt, int result )
{
mbedtls_mpi N, P, Pp, Q, Qp, D, E;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "test_suite_rsa";
mbedtls_mpi_init( &N );
mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
mbedtls_mpi_init( &Pp ); mbedtls_mpi_init( &Qp );
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E );
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen( pers ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &Qp, radix_P, output_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &Pp, radix_Q, output_Q ) == 0 );
if( corrupt )
TEST_ASSERT( mbedtls_mpi_add_int( &D, &D, 2 ) == 0 );
/* Try to deduce P, Q from N, D, E only. */
TEST_ASSERT( mbedtls_rsa_deduce_moduli( &N, &D, &E, mbedtls_ctr_drbg_random,
&ctr_drbg, &P, &Q ) == result );
if( !corrupt )
{
/* Check if (P,Q) = (Pp, Qp) or (P,Q) = (Qp, Pp) */
TEST_ASSERT( ( mbedtls_mpi_cmp_mpi( &P, &Pp ) == 0 && mbedtls_mpi_cmp_mpi( &Q, &Qp ) == 0 ) ||
( mbedtls_mpi_cmp_mpi( &P, &Qp ) == 0 && mbedtls_mpi_cmp_mpi( &Q, &Pp ) == 0 ) );
}
exit:
mbedtls_mpi_free( &N );
mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
mbedtls_mpi_free( &Pp ); mbedtls_mpi_free( &Qp );
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_rsa_deduce_private( int radix_P, char *input_P,
int radix_Q, char *input_Q,
int radix_E, char *input_E,
int radix_D, char *output_D,
int corrupt, int result )
{
mbedtls_mpi P, Q, D, Dp, E, R, Rp;
mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &Dp );
mbedtls_mpi_init( &E );
mbedtls_mpi_init( &R ); mbedtls_mpi_init( &Rp );
TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_string( &Dp, radix_D, output_D ) == 0 );
if( corrupt )
{
/* Make E even */
TEST_ASSERT( mbedtls_mpi_set_bit( &E, 0, 0 ) == 0 );
}
/* Try to deduce D from N, P, Q, E. */
TEST_ASSERT( mbedtls_rsa_deduce_private( &P, &Q, &D, &E ) == result );
if( !corrupt )
{
/*
* Check that D and Dp agree modulo LCM(P-1, Q-1).
*/
/* Replace P,Q by P-1, Q-1 */
TEST_ASSERT( mbedtls_mpi_sub_int( &P, &P, 1 ) == 0 );
TEST_ASSERT( mbedtls_mpi_sub_int( &Q, &Q, 1 ) == 0 );
/* Check D == Dp modulo P-1 */
TEST_ASSERT( mbedtls_mpi_mod_mpi( &R, &D, &P ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &Rp, &Dp, &P ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R, &Rp ) == 0 );
/* Check D == Dp modulo Q-1 */
TEST_ASSERT( mbedtls_mpi_mod_mpi( &R, &D, &Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_mod_mpi( &Rp, &Dp, &Q ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R, &Rp ) == 0 );
}
exit:
mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &Dp );
mbedtls_mpi_free( &E );
mbedtls_mpi_free( &R ); mbedtls_mpi_free( &Rp );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_CTR_DRBG_C:MBEDTLS_ENTROPY_C */
void mbedtls_rsa_import( int radix_N, char *input_N,
int radix_P, char *input_P,
int radix_Q, char *input_Q,
int radix_D, char *input_D,
int radix_E, char *input_E,
int successive,
int result )
{
mbedtls_mpi N, P, Q, D, E;
mbedtls_rsa_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "test_suite_rsa";
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen( pers ) ) == 0 );
mbedtls_rsa_init( &ctx, 0, 0 );
mbedtls_mpi_init( &N );
mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E );
if( strlen( input_N ) )
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
if( strlen( input_P ) )
TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
if( strlen( input_Q ) )
TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
if( strlen( input_D ) )
TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
if( strlen( input_E ) )
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
if( !successive )
{
TEST_ASSERT( mbedtls_rsa_import( &ctx,
strlen( input_N ) ? &N : NULL,
strlen( input_P ) ? &P : NULL,
strlen( input_Q ) ? &Q : NULL,
strlen( input_D ) ? &D : NULL,
strlen( input_E ) ? &E : NULL ) == 0 );
}
else
{
/* Import N, P, Q, D, E separately.
* This should make no functional difference. */
TEST_ASSERT( mbedtls_rsa_import( &ctx,
strlen( input_N ) ? &N : NULL,
NULL, NULL, NULL, NULL ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx,
NULL,
strlen( input_P ) ? &P : NULL,
NULL, NULL, NULL ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx,
NULL, NULL,
strlen( input_Q ) ? &Q : NULL,
NULL, NULL ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx,
NULL, NULL, NULL,
strlen( input_D ) ? &D : NULL,
NULL ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx,
NULL, NULL, NULL, NULL,
strlen( input_E ) ? &E : NULL ) == 0 );
}
TEST_ASSERT( mbedtls_rsa_complete( &ctx,
mbedtls_ctr_drbg_random,
&ctr_drbg ) == result );
exit:
mbedtls_rsa_free( &ctx );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
mbedtls_mpi_free( &N );
mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_CTR_DRBG_C:MBEDTLS_ENTROPY_C */
void mbedtls_rsa_import_raw( char *input_N,
char *input_P, char *input_Q,
char *input_D, char *input_E,
int successive,
int result )
{
unsigned char bufN[1000];
unsigned char bufP[1000];
unsigned char bufQ[1000];
unsigned char bufD[1000];
unsigned char bufE[1000];
size_t lenN = 0;
size_t lenP = 0;
size_t lenQ = 0;
size_t lenD = 0;
size_t lenE = 0;
mbedtls_rsa_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "test_suite_rsa";
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
&entropy, (const unsigned char *) pers,
strlen( pers ) ) == 0 );
mbedtls_rsa_init( &ctx, 0, 0 );
if( strlen( input_N ) )
lenN = unhexify( bufN, input_N );
if( strlen( input_P ) )
lenP = unhexify( bufP, input_P );
if( strlen( input_Q ) )
lenQ = unhexify( bufQ, input_Q );
if( strlen( input_D ) )
lenD = unhexify( bufD, input_D );
if( strlen( input_E ) )
lenE = unhexify( bufE, input_E );
if( !successive )
{
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
( lenN > 0 ) ? bufN : NULL, lenN,
( lenP > 0 ) ? bufP : NULL, lenP,
( lenQ > 0 ) ? bufQ : NULL, lenQ,
( lenD > 0 ) ? bufD : NULL, lenD,
( lenE > 0 ) ? bufE : NULL, lenE ) == 0 );
}
else
{
/* Import N, P, Q, D, E separately.
* This should make no functional difference. */
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
( lenN > 0 ) ? bufN : NULL, lenN,
NULL, 0, NULL, 0, NULL, 0, NULL, 0 ) == 0 );
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
NULL, 0,
( lenP > 0 ) ? bufP : NULL, lenP,
NULL, 0, NULL, 0, NULL, 0 ) == 0 );
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
NULL, 0, NULL, 0,
( lenQ > 0 ) ? bufQ : NULL, lenQ,
NULL, 0, NULL, 0 ) == 0 );
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
NULL, 0, NULL, 0, NULL, 0,
( lenD > 0 ) ? bufD : NULL, lenD,
NULL, 0 ) == 0 );
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
( lenE > 0 ) ? bufE : NULL, lenE ) == 0 );
}
TEST_ASSERT( mbedtls_rsa_complete( &ctx,
mbedtls_ctr_drbg_random,
&ctr_drbg ) == result );
exit:
mbedtls_rsa_free( &ctx );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void rsa_selftest()
{
TEST_ASSERT( mbedtls_rsa_self_test( 1 ) == 0 );
}
/* END_CASE */