Merge pull request #5728 from superna9999/5711-pk-opaque-rsa-pss-sign

RSA-PSS sign 1: PK
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 7e056db..dc808e8 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -917,16 +917,20 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 /**
- * \brief           Turn an EC key into an opaque one.
+ * \brief           Turn an EC or RSA key into an opaque one.
  *
  * \warning         This is a temporary utility function for tests. It might
  *                  change or be removed at any time without notice.
  *
- * \note            Only ECDSA keys are supported so far. Signing with the
- *                  specified hash & ECDH key agreement derivation operation
- *                  are the only allowed use of that key.
+ * \note            ECDSA & RSA keys are supported.
+ *                  For both key types, signing with the specified hash
+ *                  is the only allowed use of that key with PK API.
+ *                  The RSA key supports RSA-PSS signing with the specified
+ *                  hash with the PK EXT API.
+ *                  In addition, the ECDSA key is also allowed for ECDH key
+ *                  agreement derivation operation using the PSA API.
  *
- * \param pk        Input: the EC key to import to a PSA key.
+ * \param pk        Input: the EC or RSA key to import to a PSA key.
  *                  Output: a PK context wrapping that PSA key.
  * \param key       Output: a PSA key identifier.
  *                  It's the caller's responsibility to call
diff --git a/library/pk.c b/library/pk.c
index 0f465cd..bba2ef7 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -550,10 +550,23 @@
         return( mbedtls_pk_sign( ctx, md_alg, hash, hash_len,
                                  sig, sig_size, sig_len, f_rng, p_rng ) );
     }
+
 #if defined(MBEDTLS_RSA_C)
     psa_md_alg = mbedtls_psa_translate_md( md_alg );
     if( psa_md_alg == 0 )
         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+    if( mbedtls_pk_get_type( ctx ) == MBEDTLS_PK_OPAQUE )
+    {
+        const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
+        psa_status_t status;
+
+        status = psa_sign_hash( *key, PSA_ALG_RSA_PSS( psa_md_alg ),
+                                hash, hash_len,
+                                sig, sig_size, sig_len );
+        return( mbedtls_pk_error_from_psa_rsa( status ) );
+    }
+
     return( mbedtls_pk_psa_rsa_sign_ext( PSA_ALG_RSA_PSS( psa_md_alg ),
                                          ctx->pk_ctx, hash, hash_len,
                                          sig, sig_size, sig_len ) );
@@ -776,6 +789,8 @@
         psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
         psa_set_key_algorithm( &attributes,
                                PSA_ALG_RSA_PKCS1V15_SIGN( hash_alg ) );
+        psa_set_key_enrollment_algorithm( &attributes,
+                                          PSA_ALG_RSA_PSS( hash_alg ) );
 
         /* import private key into PSA */
         status = psa_import_key( &attributes,
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index a9c3c71..852c46e 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -1501,7 +1501,8 @@
 
 static int pk_opaque_rsa_can_do( mbedtls_pk_type_t type )
 {
-    return( type == MBEDTLS_PK_RSA );
+    return( type == MBEDTLS_PK_RSA ||
+            type == MBEDTLS_PK_RSASSA_PSS );
 }
 
 static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 323efc2..306cfd7 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -386,3 +386,26 @@
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C
 pk_psa_sign_ext:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP521R1:MBEDTLS_PK_ECDSA:MBEDTLS_MD_SHA512
 
+PK wrapped Sign ext:RSA2048,PK_RSA,MD_SHA256
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA256
+
+PK wrapped Sign ext:RSA2048,PK_RSASSA_PSS,MD_SHA256
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256
+
+PK wrapped Sign ext:RSA2048,PK_RSA,MD_SHA384
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_SHA384_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA384
+
+PK wrapped Sign ext:RSA2048,PK_RSASSA_PSS,MD_SHA384
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_SHA384_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA384
+
+PK wrapped Sign ext:RSA2048,PK_RSA,MD_SHA512
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_SHA512_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA512
+
+PK wrapped Sign ext:RSA2048,PK_RSASSA_PSS,MD_SHA512
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:MBEDTLS_RSA_C
+pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA512
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 6c4f9e4..8fd5367 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -1208,3 +1208,71 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_USE_PSA_CRYPTO */
+void pk_psa_wrap_sign_ext( int pk_type, int parameter, int key_pk_type, int md_alg )
+{
+    /* See the description of mbedtls_rsa_gen_key() for the description of the `parameter` argument. */
+    mbedtls_pk_context pk;
+    size_t sig_len, pkey_len;
+    mbedtls_svc_key_id_t key_id;
+    unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
+    unsigned char pkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+    unsigned char *pkey_start;
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    psa_algorithm_t psa_md_alg = mbedtls_psa_translate_md( md_alg );
+    size_t hash_len = PSA_HASH_LENGTH( psa_md_alg );
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
+    void const *options = NULL;
+    mbedtls_pk_rsassa_pss_options rsassa_pss_options;
+    int ret;
+
+    mbedtls_pk_init( &pk );
+    PSA_INIT();
+
+    /* Create legacy RSA public/private key in PK context. */
+    mbedtls_pk_init( &pk );
+    TEST_EQUAL( mbedtls_pk_setup( &pk,
+                        mbedtls_pk_info_from_type( pk_type ) ), 0 );
+    TEST_EQUAL( mbedtls_rsa_gen_key( mbedtls_pk_rsa( pk ),
+                                     mbedtls_test_rnd_std_rand, NULL,
+                                     parameter, 3 ), 0 );
+
+    /* Export underlying public key for re-importing in a legacy context. */
+    ret = mbedtls_pk_write_pubkey_der( &pk, pkey, sizeof( pkey ) );
+    TEST_ASSERT( ret >= 0 );
+
+    pkey_len = (size_t) ret;
+    /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
+    pkey_start = pkey + sizeof( pkey ) - pkey_len;
+
+    /* Turn PK context into an opaque one. */
+    TEST_EQUAL( mbedtls_pk_wrap_as_opaque( &pk, &key_id, psa_md_alg ), 0 );
+
+    memset( hash, 0x2a, sizeof( hash ) );
+    memset( sig, 0, sizeof( sig ) );
+
+    TEST_EQUAL( mbedtls_pk_sign_ext( key_pk_type, &pk, md_alg, hash, hash_len,
+                                     sig, sizeof( sig ), &sig_len,
+                                     mbedtls_test_rnd_std_rand, NULL ), 0 );
+
+    mbedtls_pk_free( &pk );
+    TEST_EQUAL( PSA_SUCCESS, psa_destroy_key( key_id ) );
+
+    mbedtls_pk_init( &pk );
+    TEST_EQUAL( mbedtls_pk_parse_public_key( &pk, pkey_start, pkey_len ), 0 );
+
+    if( key_pk_type == MBEDTLS_PK_RSASSA_PSS )
+    {
+        rsassa_pss_options.mgf1_hash_id = md_alg;
+        TEST_ASSERT( md_info != NULL );
+        rsassa_pss_options.expected_salt_len = mbedtls_md_get_size( md_info );
+        options = (const void*) &rsassa_pss_options;
+    }
+    TEST_EQUAL( mbedtls_pk_verify_ext( key_pk_type, options, &pk, md_alg,
+                                       hash, hash_len, sig, sig_len ), 0 );
+
+exit:
+    mbedtls_pk_free( &pk );
+    PSA_DONE( );
+}
+/* END_CASE */