mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-12-27 20:25:37 +00:00
d3f978bd95
Functional tests for various payload sizes and output buffer sizes. When the padding is bad or the plaintext is too large for the output buffer, verify that function writes some outputs. This doesn't validate that the implementation is time-constant, but it at least validates that it doesn't just return early without outputting anything.
358 lines
14 KiB
Plaintext
358 lines
14 KiB
Plaintext
/* BEGIN_HEADER */
|
|
#include "mbedtls/rsa.h"
|
|
#include "mbedtls/md.h"
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void pkcs1_rsaes_v15_encrypt( int mod, int radix_N, char *input_N, int radix_E,
|
|
char *input_E, int hash,
|
|
char *message_hex_string, char *seed,
|
|
char *result_hex_str, int result )
|
|
{
|
|
unsigned char message_str[1000];
|
|
unsigned char output[1000];
|
|
unsigned char output_str[1000];
|
|
unsigned char rnd_buf[1000];
|
|
mbedtls_rsa_context ctx;
|
|
size_t msg_len;
|
|
rnd_buf_info info;
|
|
mbedtls_mpi N, E;
|
|
|
|
info.length = unhexify( rnd_buf, seed );
|
|
info.buf = rnd_buf;
|
|
|
|
mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
|
|
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
|
|
memset( message_str, 0x00, 1000 );
|
|
memset( output, 0x00, 1000 );
|
|
memset( output_str, 0x00, 1000 );
|
|
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
|
|
TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
|
|
|
|
msg_len = unhexify( message_str, message_hex_string );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_pkcs1_encrypt( &ctx, &rnd_buffer_rand, &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_mpi_free( &N ); mbedtls_mpi_free( &E );
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void pkcs1_rsaes_v15_decrypt( 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 hash, char *result_hex_str, char *seed,
|
|
char *message_hex_string, int result )
|
|
{
|
|
unsigned char message_str[1000];
|
|
unsigned char output[1000];
|
|
unsigned char output_str[1000];
|
|
mbedtls_rsa_context ctx;
|
|
size_t output_len;
|
|
rnd_pseudo_info rnd_info;
|
|
mbedtls_mpi N, P, Q, E;
|
|
((void) seed);
|
|
|
|
mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P );
|
|
mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
|
|
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
|
|
|
|
memset( message_str, 0x00, 1000 );
|
|
memset( output, 0x00, 1000 );
|
|
memset( output_str, 0x00, 1000 );
|
|
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
|
|
|
|
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( &N, radix_N, input_N ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
|
|
TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
|
|
|
|
unhexify( message_str, message_hex_string );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx, &rnd_pseudo_rand, &rnd_info, MBEDTLS_RSA_PRIVATE, &output_len, message_str, output, 1000 ) == 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( &N ); mbedtls_mpi_free( &P );
|
|
mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &E );
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void pkcs1_v15_decode( int mode,
|
|
char *input_hex,
|
|
int expected_plaintext_length_arg,
|
|
int output_size_arg,
|
|
int expected_result )
|
|
{
|
|
size_t input_len;
|
|
size_t expected_plaintext_length = expected_plaintext_length_arg;
|
|
size_t output_size = output_size_arg;
|
|
rnd_pseudo_info rnd_info;
|
|
mbedtls_mpi Nmpi, Empi, Pmpi, Qmpi;
|
|
mbedtls_rsa_context ctx;
|
|
static unsigned char N[128] = {
|
|
0xc4, 0x79, 0x4c, 0x6d, 0xb2, 0xe9, 0xdf, 0xc5,
|
|
0xe5, 0xd7, 0x55, 0x4b, 0xfb, 0x6c, 0x2e, 0xec,
|
|
0x84, 0xd0, 0x88, 0x12, 0xaf, 0xbf, 0xb4, 0xf5,
|
|
0x47, 0x3c, 0x7e, 0x92, 0x4c, 0x58, 0xc8, 0x73,
|
|
0xfe, 0x8f, 0x2b, 0x8f, 0x8e, 0xc8, 0x5c, 0xf5,
|
|
0x05, 0xeb, 0xfb, 0x0d, 0x7b, 0x2a, 0x93, 0xde,
|
|
0x15, 0x0d, 0xc8, 0x13, 0xcf, 0xd2, 0x6f, 0x0d,
|
|
0x9d, 0xad, 0x30, 0xe5, 0x70, 0x20, 0x92, 0x9e,
|
|
0xb3, 0x6b, 0xba, 0x5c, 0x50, 0x0f, 0xc3, 0xb2,
|
|
0x7e, 0x64, 0x07, 0x94, 0x7e, 0xc9, 0x4e, 0xc1,
|
|
0x65, 0x04, 0xaf, 0xb3, 0x9f, 0xde, 0xa8, 0x46,
|
|
0xfa, 0x6c, 0xf3, 0x03, 0xaf, 0x1c, 0x1b, 0xec,
|
|
0x75, 0x44, 0x66, 0x77, 0xc9, 0xde, 0x51, 0x33,
|
|
0x64, 0x27, 0xb0, 0xd4, 0x8d, 0x31, 0x6a, 0x11,
|
|
0x27, 0x3c, 0x99, 0xd4, 0x22, 0xc0, 0x9d, 0x12,
|
|
0x01, 0xc7, 0x4a, 0x73, 0xac, 0xbf, 0xc2, 0xbb
|
|
};
|
|
static unsigned char E[1] = { 0x03 };
|
|
static unsigned char P[64] = {
|
|
0xe5, 0x53, 0x1f, 0x88, 0x51, 0xee, 0x59, 0xf8,
|
|
0xc1, 0xe4, 0xcc, 0x5b, 0xb3, 0x75, 0x8d, 0xc8,
|
|
0xe8, 0x95, 0x2f, 0xd0, 0xef, 0x37, 0xb4, 0xcd,
|
|
0xd3, 0x9e, 0x48, 0x8b, 0x81, 0x58, 0x60, 0xb9,
|
|
0x27, 0x1d, 0xb6, 0x28, 0x92, 0x64, 0xa3, 0xa5,
|
|
0x64, 0xbd, 0xcc, 0x53, 0x68, 0xdd, 0x3e, 0x55,
|
|
0xea, 0x9d, 0x5e, 0xcd, 0x1f, 0x96, 0x87, 0xf1,
|
|
0x29, 0x75, 0x92, 0x70, 0x8f, 0x28, 0xfb, 0x2b
|
|
};
|
|
static unsigned char Q[64] = {
|
|
0xdb, 0x53, 0xef, 0x74, 0x61, 0xb4, 0x20, 0x3b,
|
|
0x3b, 0x87, 0x76, 0x75, 0x81, 0x56, 0x11, 0x03,
|
|
0x59, 0x31, 0xe3, 0x38, 0x4b, 0x8c, 0x7a, 0x9c,
|
|
0x05, 0xd6, 0x7f, 0x1e, 0x5e, 0x60, 0xf0, 0x4e,
|
|
0x0b, 0xdc, 0x34, 0x54, 0x1c, 0x2e, 0x90, 0x83,
|
|
0x14, 0xef, 0xc0, 0x96, 0x5c, 0x30, 0x10, 0xcc,
|
|
0xc1, 0xba, 0xa0, 0x54, 0x3f, 0x96, 0x24, 0xca,
|
|
0xa3, 0xfb, 0x55, 0xbc, 0x71, 0x29, 0x4e, 0xb1
|
|
};
|
|
unsigned char original[128];
|
|
unsigned char intermediate[128];
|
|
static unsigned char default_content[128] = {
|
|
/* A randomly generated pattern. */
|
|
0x4c, 0x27, 0x54, 0xa0, 0xce, 0x0d, 0x09, 0x4a,
|
|
0x1c, 0x38, 0x8e, 0x2d, 0xa3, 0xc4, 0xe0, 0x19,
|
|
0x4c, 0x99, 0xb2, 0xbf, 0xe6, 0x65, 0x7e, 0x58,
|
|
0xd7, 0xb6, 0x8a, 0x05, 0x2f, 0xa5, 0xec, 0xa4,
|
|
0x35, 0xad, 0x10, 0x36, 0xff, 0x0d, 0x08, 0x50,
|
|
0x74, 0x47, 0xc9, 0x9c, 0x4a, 0xe7, 0xfd, 0xfa,
|
|
0x83, 0x5f, 0x14, 0x5a, 0x1e, 0xe7, 0x35, 0x08,
|
|
0xad, 0xf7, 0x0d, 0x86, 0xdf, 0xb8, 0xd4, 0xcf,
|
|
0x32, 0xb9, 0x5c, 0xbe, 0xa3, 0xd2, 0x89, 0x70,
|
|
0x7b, 0xc6, 0x48, 0x7e, 0x58, 0x4d, 0xf3, 0xef,
|
|
0x34, 0xb7, 0x57, 0x54, 0x79, 0xc5, 0x8e, 0x0a,
|
|
0xa3, 0xbf, 0x6d, 0x42, 0x83, 0x25, 0x13, 0xa2,
|
|
0x95, 0xc0, 0x0d, 0x32, 0xec, 0x77, 0x91, 0x2b,
|
|
0x68, 0xb6, 0x8c, 0x79, 0x15, 0xfb, 0x94, 0xde,
|
|
0xb9, 0x2b, 0x94, 0xb3, 0x28, 0x23, 0x86, 0x3d,
|
|
0x37, 0x00, 0xe6, 0xf1, 0x1f, 0x4e, 0xd4, 0x42
|
|
};
|
|
unsigned char final[128];
|
|
size_t output_length = 0x7EA0;
|
|
|
|
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
|
|
mbedtls_mpi_init( &Nmpi ); mbedtls_mpi_init( &Empi );
|
|
mbedtls_mpi_init( &Pmpi ); mbedtls_mpi_init( &Qmpi );
|
|
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
|
|
|
|
TEST_ASSERT( mbedtls_mpi_read_binary( &Nmpi, N, sizeof( N ) ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_binary( &Empi, E, sizeof( E ) ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_binary( &Pmpi, P, sizeof( P ) ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_binary( &Qmpi, Q, sizeof( Q ) ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_import( &ctx, &Nmpi, &Pmpi, &Qmpi,
|
|
NULL, &Empi ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
|
|
|
|
input_len = unhexify( original, input_hex );
|
|
memset( original + input_len, 'd', sizeof( original ) - input_len );
|
|
if( mode == MBEDTLS_RSA_PRIVATE )
|
|
TEST_ASSERT( mbedtls_rsa_public( &ctx, original, intermediate ) == 0 );
|
|
else
|
|
TEST_ASSERT( mbedtls_rsa_private( &ctx, &rnd_pseudo_rand, &rnd_info,
|
|
original, intermediate ) == 0 );
|
|
|
|
memcpy( final, default_content, sizeof( final ) );
|
|
TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx,
|
|
&rnd_pseudo_rand, &rnd_info,
|
|
mode,
|
|
&output_length,
|
|
intermediate,
|
|
final,
|
|
output_size ) == expected_result );
|
|
if( expected_result == 0 )
|
|
{
|
|
TEST_ASSERT( output_length == expected_plaintext_length );
|
|
TEST_ASSERT( memcmp( original + sizeof( N ) - output_length,
|
|
final,
|
|
output_length ) == 0 );
|
|
}
|
|
else if( expected_result == MBEDTLS_ERR_RSA_INVALID_PADDING ||
|
|
expected_result == MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE )
|
|
{
|
|
size_t max_payload_length =
|
|
output_size > sizeof( N ) - 11 ? sizeof( N ) - 11 : output_size;
|
|
size_t i;
|
|
size_t count = 0;
|
|
|
|
#if !defined(MBEDTLS_RSA_ALT)
|
|
/* Check that the output in invalid cases is what the default
|
|
* implementation currently does. Alternative implementations
|
|
* may produce different output, so we only perform these precise
|
|
* checks when using the default implementation. */
|
|
TEST_ASSERT( output_length == max_payload_length );
|
|
for( i = 0; i < max_payload_length; i++ )
|
|
TEST_ASSERT( final[i] == 0 );
|
|
#endif
|
|
/* Even in alternative implementations, the outputs must have
|
|
* changed, otherwise it indicates at least a timing vulnerability
|
|
* because no write to the outputs is performed in the bad case. */
|
|
TEST_ASSERT( output_length != 0x7EA0 );
|
|
for( i = 0; i < max_payload_length; i++ )
|
|
count += ( final[i] == default_content[i] );
|
|
/* If more than 16 bytes are unchanged in final, that's evidence
|
|
* that final wasn't overwritten. */
|
|
TEST_ASSERT( count < 16 );
|
|
}
|
|
|
|
exit:
|
|
mbedtls_mpi_free( &Nmpi ); mbedtls_mpi_free( &Empi );
|
|
mbedtls_mpi_free( &Pmpi ); mbedtls_mpi_free( &Qmpi );
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void pkcs1_rsassa_v15_sign( 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 digest, int hash,
|
|
char *message_hex_string, char *salt,
|
|
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];
|
|
unsigned char rnd_buf[1000];
|
|
mbedtls_rsa_context ctx;
|
|
mbedtls_mpi N, P, Q, E;
|
|
size_t msg_len;
|
|
rnd_buf_info info;
|
|
|
|
info.length = unhexify( rnd_buf, salt );
|
|
info.buf = rnd_buf;
|
|
|
|
mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P );
|
|
mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &E );
|
|
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
|
|
|
|
memset( message_str, 0x00, 1000 );
|
|
memset( hash_result, 0x00, 1000 );
|
|
memset( output, 0x00, 1000 );
|
|
memset( output_str, 0x00, 1000 );
|
|
|
|
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( &N, radix_N, input_N ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
|
|
TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 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_buffer_rand, &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( &N ); mbedtls_mpi_free( &P );
|
|
mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &E );
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void pkcs1_rsassa_v15_verify( int mod, int radix_N, char *input_N, int radix_E,
|
|
char *input_E, int digest, int hash,
|
|
char *message_hex_string, char *salt,
|
|
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;
|
|
size_t msg_len;
|
|
mbedtls_mpi N, E;
|
|
((void) salt);
|
|
|
|
mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E );
|
|
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
|
|
memset( message_str, 0x00, 1000 );
|
|
memset( hash_result, 0x00, 1000 );
|
|
memset( result_str, 0x00, 1000 );
|
|
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
|
|
TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
|
|
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_mpi_free( &N ); mbedtls_mpi_free( &E );
|
|
mbedtls_rsa_free( &ctx );
|
|
}
|
|
/* END_CASE */
|