Add tests for PKCS#1 v1.5 decoding

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.
This commit is contained in:
Gilles Peskine 2018-10-05 18:15:25 +02:00
parent ec2a5fdee1
commit 695a34654a
2 changed files with 238 additions and 0 deletions

View file

@ -33,3 +33,93 @@ pkcs1_rsassa_v15_sign:1024:16:"d17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0
RSASSA-V15 Verification Test Vector Int RSASSA-V15 Verification Test Vector Int
pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0 pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0
RSAES-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:117:0
RSAES-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:128:0
RSAES-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:116:0
RSAES-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:117:0
RSAES-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"00025050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":1:1:0
RSAES-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":0:0:0
RSAES-V15 decoding: payload=max, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:116:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: payload=max-1, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:115:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0102505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (0 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0000505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (1 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0001505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000200":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050500000ffffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:117:0
EMSA-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:128:0
EMSA-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:116:0
EMSA-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:117:0
EMSA-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":1:1:0
EMSA-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":0:0:0
EMSA-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0101ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (0 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (2 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0002ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"000100":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffff0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffe00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING

View file

@ -93,6 +93,154 @@ exit:
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void pkcs1_v15_decode( int mode,
data_t *input,
int expected_plaintext_length_arg,
int output_size_arg,
int expected_result )
{
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 );
TEST_ASSERT( input->len <= sizeof( N ) );
memcpy( original, input->x, input->len );
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 */ /* BEGIN_CASE */
void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q, 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, char * input_Q, int radix_N, char * input_N,