mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-23 05:55:40 +01:00
ce00263bd2
This commit adds test for the new library function mbedtls_rsa_check_params for checking a set of RSA core parameters. There are some toy example tests with small numbers that can be verified by hand, as well as tests with real world numbers. Complete, partial and corrupted data are tested, as well the check for primality exactly if a PRNG is provided.
1335 lines
46 KiB
Plaintext
1335 lines
46 KiB
Plaintext
/* 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 */
|
|
void mbedtls_rsa_export( 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 )
|
|
{
|
|
/* Original MPI's with which we set up the RSA context */
|
|
mbedtls_mpi N, P, Q, D, E;
|
|
|
|
/* Exported MPI's */
|
|
mbedtls_mpi Ne, Pe, Qe, De, Ee;
|
|
|
|
const int have_N = ( strlen( input_N ) > 0 );
|
|
const int have_P = ( strlen( input_P ) > 0 );
|
|
const int have_Q = ( strlen( input_Q ) > 0 );
|
|
const int have_D = ( strlen( input_D ) > 0 );
|
|
const int have_E = ( strlen( input_E ) > 0 );
|
|
|
|
const int is_priv = have_P || have_Q || have_D;
|
|
|
|
mbedtls_rsa_context ctx;
|
|
|
|
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 );
|
|
|
|
mbedtls_mpi_init( &Ne );
|
|
mbedtls_mpi_init( &Pe ); mbedtls_mpi_init( &Qe );
|
|
mbedtls_mpi_init( &De ); mbedtls_mpi_init( &Ee );
|
|
|
|
/* Setup RSA context */
|
|
|
|
if( have_N )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
|
|
|
|
if( have_P )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
|
|
|
|
if( have_Q )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
|
|
|
|
if( have_D )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
|
|
|
|
if( have_E )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
|
|
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 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_complete( &ctx, NULL, NULL ) == 0 );
|
|
|
|
/*
|
|
* Export parameters and compare to original ones.
|
|
*/
|
|
|
|
/* N and E must always be present. */
|
|
if( !successive )
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, &Ne, NULL, NULL, NULL, &Ee ) == 0 );
|
|
}
|
|
else
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, &Ne, NULL, NULL, NULL, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, NULL, NULL, NULL, NULL, &Ee ) == 0 );
|
|
}
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &N, &Ne ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &E, &Ee ) == 0 );
|
|
|
|
/* If we were providing enough information to setup a complete private context,
|
|
* we expect to be able to export all core parameters. */
|
|
|
|
if( is_priv )
|
|
{
|
|
if( !successive )
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, NULL, &Pe, &Qe,
|
|
&De, NULL ) == 0 );
|
|
}
|
|
else
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, NULL, &Pe, NULL,
|
|
NULL, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, NULL, NULL, &Qe,
|
|
NULL, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_export( &ctx, NULL, NULL, NULL,
|
|
&De, NULL ) == 0 );
|
|
}
|
|
|
|
if( have_P )
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P, &Pe ) == 0 );
|
|
|
|
if( have_Q )
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Q, &Qe ) == 0 );
|
|
|
|
if( have_D )
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &D, &De ) == 0 );
|
|
|
|
/* While at it, perform a sanity check */
|
|
TEST_ASSERT( mbedtls_rsa_check_params( &Ne, &Pe, &Qe, &De, &Ee,
|
|
NULL, NULL ) == 0 );
|
|
}
|
|
|
|
exit:
|
|
|
|
mbedtls_rsa_free( &ctx );
|
|
|
|
mbedtls_mpi_free( &N );
|
|
mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
|
|
mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E );
|
|
|
|
mbedtls_mpi_free( &Ne );
|
|
mbedtls_mpi_free( &Pe ); mbedtls_mpi_free( &Qe );
|
|
mbedtls_mpi_free( &De ); mbedtls_mpi_free( &Ee );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void mbedtls_rsa_check_params( 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 prng, int result )
|
|
{
|
|
/* Original MPI's with which we set up the RSA context */
|
|
mbedtls_mpi N, P, Q, D, E;
|
|
|
|
const int have_N = ( strlen( input_N ) > 0 );
|
|
const int have_P = ( strlen( input_P ) > 0 );
|
|
const int have_Q = ( strlen( input_Q ) > 0 );
|
|
const int have_D = ( strlen( input_D ) > 0 );
|
|
const int have_E = ( strlen( input_E ) > 0 );
|
|
|
|
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( &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 );
|
|
|
|
if( have_N )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
|
|
|
|
if( have_P )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
|
|
|
|
if( have_Q )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
|
|
|
|
if( have_D )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
|
|
|
|
if( have_E )
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_check_params( have_N ? &N : NULL,
|
|
have_P ? &P : NULL,
|
|
have_Q ? &Q : NULL,
|
|
have_D ? &D : NULL,
|
|
have_E ? &E : NULL,
|
|
prng ? mbedtls_ctr_drbg_random : NULL,
|
|
prng ? &ctr_drbg : NULL ) == result );
|
|
exit:
|
|
|
|
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_export_raw( char *input_N, char *input_P,
|
|
char *input_Q, char *input_D,
|
|
char *input_E, int successive )
|
|
{
|
|
/* Original raw buffers with which we set up the RSA context */
|
|
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;
|
|
|
|
/* Exported buffers */
|
|
unsigned char bufNe[ sizeof( bufN ) ];
|
|
unsigned char bufPe[ sizeof( bufP ) ];
|
|
unsigned char bufQe[ sizeof( bufQ ) ];
|
|
unsigned char bufDe[ sizeof( bufD ) ];
|
|
unsigned char bufEe[ sizeof( bufE ) ];
|
|
|
|
const int have_N = ( strlen( input_N ) > 0 );
|
|
const int have_P = ( strlen( input_P ) > 0 );
|
|
const int have_Q = ( strlen( input_Q ) > 0 );
|
|
const int have_D = ( strlen( input_D ) > 0 );
|
|
const int have_E = ( strlen( input_E ) > 0 );
|
|
|
|
const int is_priv = have_P || have_Q || have_D;
|
|
|
|
mbedtls_rsa_context ctx;
|
|
|
|
mbedtls_rsa_init( &ctx, 0, 0 );
|
|
|
|
/* Setup RSA context */
|
|
|
|
if( have_N )
|
|
lenN = unhexify( bufN, input_N );
|
|
|
|
if( have_P )
|
|
lenP = unhexify( bufP, input_P );
|
|
|
|
if( have_Q )
|
|
lenQ = unhexify( bufQ, input_Q );
|
|
|
|
if( have_D )
|
|
lenD = unhexify( bufD, input_D );
|
|
|
|
if( have_E )
|
|
lenE = unhexify( bufE, input_E );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_import_raw( &ctx,
|
|
have_N ? bufN : NULL, lenN,
|
|
have_P ? bufP : NULL, lenP,
|
|
have_Q ? bufQ : NULL, lenQ,
|
|
have_D ? bufD : NULL, lenD,
|
|
have_E ? bufE : NULL, lenE ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_complete( &ctx, NULL, NULL ) == 0 );
|
|
|
|
/*
|
|
* Export parameters and compare to original ones.
|
|
*/
|
|
|
|
/* N and E must always be present. */
|
|
if( !successive )
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, bufNe, lenN,
|
|
NULL, 0, NULL, 0, NULL, 0,
|
|
bufEe, lenE ) == 0 );
|
|
}
|
|
else
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, bufNe, lenN,
|
|
NULL, 0, NULL, 0, NULL, 0,
|
|
NULL, 0 ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, NULL, 0,
|
|
NULL, 0, NULL, 0, NULL, 0,
|
|
bufEe, lenE ) == 0 );
|
|
}
|
|
TEST_ASSERT( memcmp( bufN, bufNe, lenN ) == 0 );
|
|
TEST_ASSERT( memcmp( bufE, bufEe, lenE ) == 0 );
|
|
|
|
/* If we were providing enough information to setup a complete private context,
|
|
* we expect to be able to export all core parameters. */
|
|
|
|
if( is_priv )
|
|
{
|
|
if( !successive )
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, NULL, 0,
|
|
bufPe, lenP ? lenP : sizeof( bufPe ),
|
|
bufQe, lenQ ? lenQ : sizeof( bufQe ),
|
|
bufDe, lenD ? lenD : sizeof( bufDe ),
|
|
NULL, 0 ) == 0 );
|
|
}
|
|
else
|
|
{
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, NULL, 0,
|
|
bufPe, lenP ? lenP : sizeof( bufPe ),
|
|
NULL, 0, NULL, 0,
|
|
NULL, 0 ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, NULL, 0, NULL, 0,
|
|
bufQe, lenQ ? lenQ : sizeof( bufQe ),
|
|
NULL, 0, NULL, 0 ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_export_raw( &ctx, NULL, 0, NULL, 0,
|
|
NULL, 0, bufDe, lenD ? lenD : sizeof( bufDe ),
|
|
NULL, 0 ) == 0 );
|
|
}
|
|
|
|
if( have_P )
|
|
TEST_ASSERT( memcmp( bufP, bufPe, lenP ) == 0 );
|
|
|
|
if( have_Q )
|
|
TEST_ASSERT( memcmp( bufQ, bufQe, lenQ ) == 0 );
|
|
|
|
if( have_D )
|
|
TEST_ASSERT( memcmp( bufD, bufDe, lenD ) == 0 );
|
|
|
|
}
|
|
|
|
exit:
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* 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 */
|