From 6e3187b2122055bbd0bf43f59d01dd4d6dc89f35 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 22 Jun 2021 18:39:53 +0200 Subject: [PATCH] RSA: Use hashlen as the hash input size as documented Where hashlen was previously ignored when the hash length could be inferred from an md_alg parameter, the two must now match. Adapt the existing tests accordingly. Adapt the sample programs accordingly. This commit does not add any negative testing. Signed-off-by: Gilles Peskine --- library/rsa.c | 20 ++++++++----- programs/pkey/dh_client.c | 2 +- programs/pkey/dh_server.c | 2 +- programs/pkey/rsa_sign.c | 2 +- programs/pkey/rsa_verify.c | 2 +- tests/suites/test_suite_pk.function | 22 +++++++------- tests/suites/test_suite_pkcs1_v15.function | 20 +++++++------ tests/suites/test_suite_pkcs1_v21.function | 35 +++++++++++++--------- tests/suites/test_suite_rsa.function | 22 +++++++------- 9 files changed, 71 insertions(+), 56 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index a788337a59a8..57b8a6f4bbe2 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1799,7 +1799,8 @@ static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, if( md_info == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); } md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); @@ -1934,14 +1935,13 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * Parameters: * - md_alg: Identifies the hash algorithm used to generate the given hash; * MBEDTLS_MD_NONE if raw data is signed. - * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hashlen: Length of hash. Must match md_alg if that's not NONE. * - hash: Buffer containing the hashed message or the raw data. * - dst_len: Length of the encoded message. * - dst: Buffer to hold the encoded message. * * Assumptions: - * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. - * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - hash has size hashlen. * - dst points to a buffer of size at least dst_len. * */ @@ -1966,7 +1966,8 @@ static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); /* Double-check that 8 + hashlen + oid_size can be used as a * 1-byte ASN.1 length encoding and that there's no overflow. */ @@ -2031,6 +2032,8 @@ static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, * TAG-NULL + LEN [ NULL ] ] * TAG-OCTET + LEN [ HASH ] ] */ + if( 0x08 + oid_size + hashlen >= 0x80 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; @@ -2212,7 +2215,8 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, if( md_info == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); } md_info = mbedtls_md_info_from_type( mgf1_hash_id ); @@ -2683,7 +2687,7 @@ int mbedtls_rsa_self_test( int verbose ) } if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, - MBEDTLS_MD_SHA1, 0, + MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext ) != 0 ) { if( verbose != 0 ) @@ -2696,7 +2700,7 @@ int mbedtls_rsa_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); - if( mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA1, 0, + if( mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext ) != 0 ) { if( verbose != 0 ) diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c index d68dc2477803..88e817eaa572 100644 --- a/programs/pkey/dh_client.c +++ b/programs/pkey/dh_client.c @@ -221,7 +221,7 @@ int main( void ) } if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA256, - 0, hash, p ) ) != 0 ) + 32, hash, p ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret ); goto exit; diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c index 9d51c14a8f0a..e469bbc0281d 100644 --- a/programs/pkey/dh_server.c +++ b/programs/pkey/dh_server.c @@ -229,7 +229,7 @@ int main( void ) buf[n + 1] = (unsigned char)( rsa.MBEDTLS_PRIVATE(len) ); if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_MD_SHA256, - 0, hash, buf + n + 2 ) ) != 0 ) + 32, hash, buf + n + 2 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret ); goto exit; diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c index d9ba3bb6eb59..ebc88e457b49 100644 --- a/programs/pkey/rsa_sign.c +++ b/programs/pkey/rsa_sign.c @@ -147,7 +147,7 @@ int main( int argc, char *argv[] ) } if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_MD_SHA256, - 20, hash, buf ) ) != 0 ) + 32, hash, buf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned -0x%0x\n\n", (unsigned int) -ret ); goto exit; diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c index fff568a3dd42..5a68246e520b 100644 --- a/programs/pkey/rsa_verify.c +++ b/programs/pkey/rsa_verify.c @@ -141,7 +141,7 @@ int main( int argc, char *argv[] ) } if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA256, - 20, hash, buf ) ) != 0 ) + 32, hash, buf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned -0x%0x\n\n", (unsigned int) -ret ); goto exit; diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 573c9d43069a..c7c5f507b9df 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -444,9 +444,10 @@ void pk_rsa_verify_ext_test_vec( data_t * message_str, int digest, if( digest != MBEDTLS_MD_NONE ) { - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), - message_str->x, message_str->len, hash_result ) == 0 ); - hash_len = 0; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, + hash_result ) == 0 ); + hash_len = mbedtls_md_get_size( md_info ); } else { @@ -611,7 +612,8 @@ void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret ) { mbedtls_pk_context pk; size_t sig_len; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + unsigned char hash[32]; // Hard-coded for SHA256 + size_t hash_len = sizeof( hash ); unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; void *rs_ctx = NULL; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) @@ -635,7 +637,7 @@ void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret ) TEST_ASSERT( pk_genkey( &pk, parameter ) == 0 ); TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256, - hash, sizeof hash, sig, &sig_len, + hash, hash_len, sig, &sig_len, mbedtls_test_rnd_std_rand, NULL, rs_ctx ) == sign_ret ); if( sign_ret == 0 ) TEST_ASSERT( sig_len <= MBEDTLS_PK_SIGNATURE_MAX_SIZE ); @@ -643,22 +645,22 @@ void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret ) sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, - hash, sizeof hash, sig, sig_len ) == verify_ret ); + hash, hash_len, sig, sig_len ) == verify_ret ); if( verify_ret == 0 ) { hash[0]++; TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, - hash, sizeof hash, sig, sig_len ) != 0 ); + hash, hash_len, sig, sig_len ) != 0 ); hash[0]--; sig[0]++; TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, - hash, sizeof hash, sig, sig_len ) != 0 ); + hash, hash_len, sig, sig_len ) != 0 ); sig[0]--; } - TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, + TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, hash_len, sig, &sig_len, mbedtls_test_rnd_std_rand, NULL ) == sign_ret ); @@ -668,7 +670,7 @@ void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret ) sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256, - hash, sizeof hash, sig, sig_len, rs_ctx ) == verify_ret ); + hash, hash_len, sig, sig_len, rs_ctx ) == verify_ret ); if( verify_ret == 0 ) { diff --git a/tests/suites/test_suite_pkcs1_v15.function b/tests/suites/test_suite_pkcs1_v15.function index d78ee88959ac..3d29f10bb179 100644 --- a/tests/suites/test_suite_pkcs1_v15.function +++ b/tests/suites/test_suite_pkcs1_v15.function @@ -269,6 +269,7 @@ void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q, data_t * result_str, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); unsigned char output[128]; mbedtls_rsa_context ctx; mbedtls_mpi N, P, Q, E; @@ -298,13 +299,13 @@ void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q, TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 ); TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); - - TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &mbedtls_test_rnd_buffer_rand, - &info, digest, 0, hash_result, - output ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_sign( + &ctx, &mbedtls_test_rnd_buffer_rand, &info, + digest, mbedtls_md_get_size( md_info ), hash_result, + output ) == result ); if( result == 0 ) { @@ -326,6 +327,7 @@ void pkcs1_rsassa_v15_verify( int mod, int radix_N, char * input_N, data_t * result_str, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); mbedtls_rsa_context ctx; mbedtls_mpi N, E; ((void) salt); @@ -343,10 +345,10 @@ void pkcs1_rsassa_v15_verify( int mod, int radix_N, char * input_N, TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); - TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, 0, hash_result, result_str->x ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, mbedtls_md_get_size( md_info ), hash_result, result_str->x ) == result ); exit: mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E ); diff --git a/tests/suites/test_suite_pkcs1_v21.function b/tests/suites/test_suite_pkcs1_v21.function index ec5591f6d1ab..27b0990d74ae 100644 --- a/tests/suites/test_suite_pkcs1_v21.function +++ b/tests/suites/test_suite_pkcs1_v21.function @@ -123,6 +123,7 @@ void pkcs1_rsassa_pss_sign( int mod, data_t * input_P, data_t * input_Q, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); unsigned char output[512]; mbedtls_rsa_context ctx; mbedtls_test_rnd_buf_info info; @@ -152,14 +153,15 @@ void pkcs1_rsassa_pss_sign( int mod, data_t * input_P, data_t * input_Q, TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 ); TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); if (fixed_salt_length == MBEDTLS_RSA_SALT_LEN_ANY) { - TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &mbedtls_test_rnd_buffer_rand, - &info, digest, 0,hash_result, - output ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_sign( + &ctx, &mbedtls_test_rnd_buffer_rand, &info, + digest, mbedtls_md_get_size( md_info ), hash_result, + output ) == result ); if( result == 0 ) { ASSERT_COMPARE( output, ctx.len, result_str->x, result_str->len ); @@ -169,9 +171,10 @@ void pkcs1_rsassa_pss_sign( int mod, data_t * input_P, data_t * input_Q, info.length = rnd_buf->len; } - TEST_ASSERT( mbedtls_rsa_rsassa_pss_sign_ext( &ctx, &mbedtls_test_rnd_buffer_rand, - &info, digest, 0, hash_result, - fixed_salt_length, output ) == result ); + TEST_ASSERT( mbedtls_rsa_rsassa_pss_sign_ext( + &ctx, &mbedtls_test_rnd_buffer_rand, &info, + digest, mbedtls_md_get_size( md_info ), hash_result, + fixed_salt_length, output ) == result ); if( result == 0 ) { ASSERT_COMPARE( output, ctx.len, result_str->x, result_str->len ); @@ -190,6 +193,7 @@ void pkcs1_rsassa_pss_verify( int mod, data_t * input_N, data_t * input_E, char * salt, data_t * result_str, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); mbedtls_rsa_context ctx; mbedtls_mpi N, E; ((void) salt); @@ -208,10 +212,10 @@ void pkcs1_rsassa_pss_verify( int mod, data_t * input_N, data_t * input_E, TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); - TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, 0, hash_result, result_str->x ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, mbedtls_md_get_size( md_info ), hash_result, result_str->x ) == result ); exit: mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E ); @@ -248,9 +252,12 @@ void pkcs1_rsassa_pss_verify_ext( int mod, data_t * input_N, data_t * input_E, if( msg_digest_id != MBEDTLS_MD_NONE ) { - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( msg_digest_id ), - message_str->x, message_str->len, hash_result ) == 0 ); - hash_len = 0; + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( msg_digest_id ); + TEST_ASSERT( mbedtls_md( md_info, + message_str->x, message_str->len, + hash_result ) == 0 ); + hash_len = mbedtls_md_get_size( md_info ); } else { diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function index 14b4afc3a34c..1bffc769e6d7 100644 --- a/tests/suites/test_suite_rsa.function +++ b/tests/suites/test_suite_rsa.function @@ -86,6 +86,7 @@ void mbedtls_rsa_pkcs1_sign( data_t * message_str, int padding_mode, data_t * result_str, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); unsigned char output[256]; mbedtls_rsa_context ctx; mbedtls_mpi N, P, Q, E; @@ -111,13 +112,13 @@ void mbedtls_rsa_pkcs1_sign( data_t * message_str, int padding_mode, TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 ); TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); - - TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &mbedtls_test_rnd_pseudo_rand, - &rnd_info, digest, 0, hash_result, - output ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_sign( + &ctx, &mbedtls_test_rnd_pseudo_rand, &rnd_info, + digest, mbedtls_md_get_size( md_info ), hash_result, + output ) == result ); if( result == 0 ) { @@ -139,8 +140,8 @@ void mbedtls_rsa_pkcs1_verify( data_t * message_str, int padding_mode, data_t * result_str, int result ) { unsigned char hash_result[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( digest ); mbedtls_rsa_context ctx; - mbedtls_mpi N, E; mbedtls_mpi_init( &N ); mbedtls_mpi_init( &E ); @@ -155,11 +156,10 @@ void mbedtls_rsa_pkcs1_verify( data_t * message_str, int padding_mode, TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) ); TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 ); + if( md_info != NULL ) + TEST_ASSERT( mbedtls_md( md_info, message_str->x, message_str->len, hash_result ) == 0 ); - if( mbedtls_md_info_from_type( digest ) != NULL ) - TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 ); - - TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, 0, hash_result, result_str->x ) == result ); + TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, digest, mbedtls_md_get_size( md_info ), hash_result, result_str->x ) == result ); exit: mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E );