Merge pull request #4736 from daverodgman/alert_bugfixes_2.x

Backport 2.x: Fix alert raised for invalid fragment length
diff --git a/ChangeLog.d/ensure_hash_len_is_valid.txt b/ChangeLog.d/ensure_hash_len_is_valid.txt
new file mode 100644
index 0000000..d3e2930
--- /dev/null
+++ b/ChangeLog.d/ensure_hash_len_is_valid.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * mbedtls_pk_sign() and mbedtls_pk_verify() and their extended and
+     restartable variants now always honor the specified hash length if
+     nonzero. Before, for RSA, hash_len was ignored in favor of the length of
+     the specified hash algorithm.
diff --git a/library/pk.c b/library/pk.c
index ecf002d..05cc213 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -235,12 +235,15 @@
 {
     const mbedtls_md_info_t *md_info;
 
-    if( *hash_len != 0 )
+    if( *hash_len != 0 && md_alg == MBEDTLS_MD_NONE )
         return( 0 );
 
     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
         return( -1 );
 
+    if ( *hash_len != 0 && *hash_len != mbedtls_md_get_size( md_info ) )
+        return ( -1 );
+
     *hash_len = mbedtls_md_get_size( md_info );
     return( 0 );
 }
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index a249ba2..82d1573 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -883,8 +883,9 @@
 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];
+    size_t sig_len, hash_len;
+    mbedtls_md_type_t md = MBEDTLS_MD_SHA256;
+    unsigned char *hash = NULL;
     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
     void *rs_ctx = NULL;
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -898,40 +899,43 @@
     mbedtls_ecp_set_max_ops( 42000 );
 #endif
 
+    hash_len = mbedtls_md_get_size( mbedtls_md_info_from_type( md ) );
+    ASSERT_ALLOC( hash, hash_len );
+
     mbedtls_pk_init( &pk );
     USE_PSA_INIT( );
 
-    memset( hash, 0x2a, sizeof hash );
+    memset( hash, 0x2a, hash_len );
     memset( sig, 0, sizeof sig );
 
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 );
     TEST_ASSERT( pk_genkey( &pk, parameter ) == 0 );
 
-    TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256,
-                 hash, sizeof hash, sig, &sig_len,
+    TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, md,
+                 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 );
     else
         sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
 
-    TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
-                            hash, sizeof hash, sig, sig_len ) == verify_ret );
+    TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                            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 );
+        TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                                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 );
+        TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                                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, md, hash, hash_len,
                                   sig, &sig_len,
                                   mbedtls_test_rnd_std_rand,
                                   NULL ) == sign_ret );
@@ -940,19 +944,19 @@
     else
         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 );
+    TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                 hash, hash_len, sig, sig_len, rs_ctx ) == verify_ret );
 
     if( verify_ret == 0 )
     {
         hash[0]++;
-        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
-                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                     hash, hash_len, sig, sig_len, rs_ctx ) != 0 );
         hash[0]--;
 
         sig[0]++;
-        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
-                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                     hash, hash_len, sig, sig_len, rs_ctx ) != 0 );
         sig[0]--;
     }
 
@@ -961,6 +965,7 @@
     mbedtls_pk_restart_free( rs_ctx );
 #endif
     mbedtls_pk_free( &pk );
+    mbedtls_free( hash );
     USE_PSA_DONE( );
 }
 /* END_CASE */