PSA crypto: asymmetric signature (RSA PKCS#1v1.5 only)

Define hash algorithms and RSA signature algorithms.

New function psa_asymmetric_sign.

Implement psa_asymmetric_sign for RSA PKCS#1 v1.5.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 741f5d1..2565232 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -41,6 +41,8 @@
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/ecp.h"
 #include "mbedtls/entropy.h"
+#include "mbedtls/md.h"
+#include "mbedtls/md_internal.h"
 #include "mbedtls/pk.h"
 #include "mbedtls/pk_internal.h"
 #include "mbedtls/rsa.h"
@@ -351,6 +353,186 @@
 
 
 /****************************************************************/
+/* Message digests */
+/****************************************************************/
+
+static const mbedtls_md_info_t *mbedtls_md_info_of_psa( psa_algorithm_t alg )
+{
+    switch( alg )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case PSA_ALG_MD2:
+            return( &mbedtls_md2_info );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case PSA_ALG_MD4:
+            return( &mbedtls_md4_info );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case PSA_ALG_MD5:
+            return( &mbedtls_md5_info );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case PSA_ALG_RIPEMD160:
+            return( &mbedtls_ripemd160_info );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case PSA_ALG_SHA_1:
+            return( &mbedtls_sha1_info );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case PSA_ALG_SHA_224:
+            return( &mbedtls_sha224_info );
+        case PSA_ALG_SHA_256:
+            return( &mbedtls_sha256_info );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case PSA_ALG_SHA_384:
+            return( &mbedtls_sha384_info );
+        case PSA_ALG_SHA_512:
+            return( &mbedtls_sha512_info );
+#endif
+        default:
+            return( NULL );
+    }
+}
+
+#if 0
+static psa_algorithm_t mbedtls_md_alg_to_psa( mbedtls_md_type_t md_alg )
+{
+    switch( md_alg )
+    {
+        case MBEDTLS_MD_NONE:
+            return( 0 );
+        case MBEDTLS_MD_MD2:
+            return( PSA_ALG_MD2 );
+        case MBEDTLS_MD_MD4:
+            return( PSA_ALG_MD4 );
+        case MBEDTLS_MD_MD5:
+            return( PSA_ALG_MD5 );
+        case MBEDTLS_MD_SHA1:
+            return( PSA_ALG_SHA_1 );
+        case MBEDTLS_MD_SHA224:
+            return( PSA_ALG_SHA_224 );
+        case MBEDTLS_MD_SHA256:
+            return( PSA_ALG_SHA_256 );
+        case MBEDTLS_MD_SHA384:
+            return( PSA_ALG_SHA_384 );
+        case MBEDTLS_MD_SHA512:
+            return( PSA_ALG_SHA_512 );
+        case MBEDTLS_MD_RIPEMD160:
+            return( PSA_ALG_RIPEMD160 );
+        default:
+            return( MBEDTLS_MD_NOT_SUPPORTED );
+    }
+}
+#endif
+
+
+
+/****************************************************************/
+/* Asymmetric cryptography */
+/****************************************************************/
+
+psa_status_t psa_asymmetric_sign(psa_key_slot_t key,
+                                 psa_algorithm_t alg,
+                                 const uint8_t *hash,
+                                 size_t hash_length,
+                                 const uint8_t *salt,
+                                 size_t salt_length,
+                                 uint8_t *signature,
+                                 size_t signature_size,
+                                 size_t *signature_length)
+{
+    key_slot_t *slot;
+
+    if( key == 0 || key > MBEDTLS_PSA_KEY_SLOT_COUNT )
+        return( PSA_ERROR_EMPTY_SLOT );
+    slot = &global_data.key_slots[key];
+    if( slot->type == PSA_KEY_TYPE_NONE )
+        return( PSA_ERROR_EMPTY_SLOT );
+    if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    (void) salt;
+    (void) salt_length;
+
+#if defined(MBEDTLS_RSA_C)
+    if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR )
+    {
+        mbedtls_rsa_context *rsa = slot->data.rsa;
+        int ret;
+        psa_algorithm_t hash_alg = PSA_ALG_RSA_GET_HASH( alg );
+        const mbedtls_md_info_t *md_info = mbedtls_md_info_of_psa( hash_alg );
+        mbedtls_md_type_t md_alg =
+            hash_alg == 0 ? MBEDTLS_MD_NONE : mbedtls_md_get_type( md_info );
+        if( md_alg == MBEDTLS_MD_NONE )
+        {
+#if SIZE_MAX > UINT_MAX
+            if( hash_length > UINT_MAX )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+#endif
+        }
+        else
+        {
+            if( mbedtls_md_get_size( md_info ) != hash_length )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+            if( md_info == NULL )
+                return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        if( signature_size < rsa->len )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+#if defined(MBEDTLS_PKCS1_V15)
+        if( PSA_ALG_IS_RSA_PKCS1V15( alg ) )
+        {
+            mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
+                                     MBEDTLS_MD_NONE );
+            ret = mbedtls_rsa_pkcs1_sign( rsa,
+                                          mbedtls_ctr_drbg_random,
+                                          &global_data.ctr_drbg,
+                                          MBEDTLS_RSA_PRIVATE,
+                                          md_alg, hash_length, hash,
+                                          signature );
+        }
+        else
+#endif /* MBEDTLS_PKCS1_V15 */
+#if defined(MBEDTLS_PKCS1_V21)
+        if( alg == PSA_ALG_RSA_PSS_MGF1 )
+        {
+            mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
+            ret = mbedtls_rsa_rsassa_pss_sign( rsa,
+                                               mbedtls_ctr_drbg_random,
+                                               &global_data.ctr_drbg,
+                                               MBEDTLS_RSA_PRIVATE,
+                                               md_alg, hash_length, hash,
+                                               signature );
+        }
+        else
+#endif /* MBEDTLS_PKCS1_V21 */
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+        *signature_length = ( ret == 0 ? rsa->len : 0 );
+        return( mbedtls_to_psa_error( ret ) );
+    }
+    else
+#endif /* defined(MBEDTLS_RSA_C) */
+#if defined(MBEDTLS_ECP_C)
+    if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+    {
+        // TODO
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+    else
+#endif /* defined(MBEDTLS_ECP_C) */
+    {
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+}
+
+
+
+/****************************************************************/
 /* Module setup */
 /****************************************************************/