Merge pull request #5355 from yuhaoth/pr/remove-duplicate-sig-alg-ext

Remove duplicate write signature algorithms extension
The failure of ABI-API-checking is expected.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 6aa4d21..f9bbf0c 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1359,11 +1359,11 @@
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    const int *MBEDTLS_PRIVATE(sig_hashes);          /*!< allowed signature hashes           */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    const uint16_t *MBEDTLS_PRIVATE(tls13_sig_algs); /*!< allowed signature algorithms for TLS 1.3 */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    const int *MBEDTLS_PRIVATE(sig_hashes);         /*!< allowed signature hashes           */
+#endif
+    const uint16_t *MBEDTLS_PRIVATE(sig_algs);      /*!< allowed signature algorithms       */
 #endif
 
 #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -3267,6 +3267,7 @@
                               const uint16_t *groups );
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
 /**
  * \brief          Set the allowed hashes for signatures during the handshake.
  *
@@ -3296,10 +3297,10 @@
  * \param hashes   Ordered list of allowed signature hashes,
  *                 terminated by \c MBEDTLS_MD_NONE.
  */
-void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
-                                  const int *hashes );
+void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
+                                                     const int *hashes );
+#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 /**
  * \brief          Configure allowed signature algorithms for use in TLS 1.3
  *
@@ -3311,7 +3312,6 @@
  */
 void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf,
                                 const uint16_t* sig_algs );
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 888523f..e411b70 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -199,107 +199,6 @@
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-/*
- * Only if we handle at least one key exchange that needs signatures.
- */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
-                                               unsigned char *buf,
-                                               const unsigned char *end,
-                                               size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t sig_alg_len = 0;
-    const int *md;
-
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
-    unsigned char *sig_alg_list = buf + 6;
-#endif
-
-    *olen = 0;
-
-    if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding signature_algorithms extension" ) );
-
-    if( ssl->conf->sig_hashes == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
-    {
-#if defined(MBEDTLS_ECDSA_C)
-        sig_alg_len += 2;
-#endif
-#if defined(MBEDTLS_RSA_C)
-        sig_alg_len += 2;
-#endif
-        if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "length in bytes of sig-hash-alg extension too big" ) );
-            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-        }
-    }
-
-    /* Empty signature algorithms list, this is a configuration error. */
-    if( sig_alg_len == 0 )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 );
-
-    /*
-     * Prepare signature_algorithms extension (TLS 1.2)
-     */
-    sig_alg_len = 0;
-
-    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
-    {
-#if defined(MBEDTLS_ECDSA_C)
-        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
-        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
-#if defined(MBEDTLS_RSA_C)
-        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
-        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-    }
-
-    /*
-     * enum {
-     *     none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
-     *     sha512(6), (255)
-     * } HashAlgorithm;
-     *
-     * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
-     *   SignatureAlgorithm;
-     *
-     * struct {
-     *     HashAlgorithm hash;
-     *     SignatureAlgorithm signature;
-     * } SignatureAndHashAlgorithm;
-     *
-     * SignatureAndHashAlgorithm
-     *   supported_signature_algorithms<2..2^16-2>;
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( sig_alg_len + 2, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( sig_alg_len, p, 0 );
-    p += 2;
-
-    *olen = 6 + sig_alg_len;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 
@@ -1131,10 +1030,10 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len,
-                                                    end, &olen ) ) != 0 )
+    if( ( ret = mbedtls_ssl_write_sig_alg_ext( ssl, p + 2 + ext_len,
+                                               end, &olen ) ) != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_sig_alg_ext", ret );
         return( ret );
     }
     ext_len += olen;
@@ -2696,7 +2595,6 @@
                                           mbedtls_md_type_t *md_alg,
                                           mbedtls_pk_type_t *pk_alg )
 {
-    ((void) ssl);
     *md_alg = MBEDTLS_MD_NONE;
     *pk_alg = MBEDTLS_PK_NONE;
 
@@ -2732,9 +2630,9 @@
     }
 
     /*
-     * Check if the hash is acceptable
+     * Check if the signature algorithm is acceptable
      */
-    if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
+    if( !mbedtls_ssl_sig_alg_is_offered( ssl, MBEDTLS_GET_UINT16_BE( *p, 0 ) ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1,
             ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) );
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 4f84a2b..788fafd 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -56,6 +56,8 @@
 #include "mbedtls/psa_util.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+#include "common.h"
+
 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
     !defined(inline) && !defined(__cplusplus)
 #define inline __inline
@@ -256,8 +258,11 @@
         : ( MBEDTLS_SSL_IN_CONTENT_LEN )                             \
         )
 
-/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */
-#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN  65534
+/* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */
+#define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN       65534
+
+/* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */
+#define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN       2
 
 /* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */
 #define MBEDTLS_SSL_MAX_CURVE_LIST_LEN         65535
@@ -554,6 +559,7 @@
 
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
     unsigned char group_list_heap_allocated;
+    unsigned char sig_algs_heap_allocated;
 #endif
 
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
@@ -592,6 +598,7 @@
 
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
     const uint16_t *group_list;
+    const uint16_t *sig_algs;
 #endif
 
 #if defined(MBEDTLS_DHM_C)
@@ -1276,11 +1283,6 @@
 int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
-                                mbedtls_md_type_t md );
-#endif
-
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
 static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value
                                                     ( const uint16_t srtp_profile_value )
@@ -1719,19 +1721,17 @@
                                                unsigned char const *msg,
                                                size_t msg_len );
 
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
- * Write TLS 1.3 Signature Algorithm extension
+ * Write Signature Algorithm extension
  */
-int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         unsigned char *end,
-                                         size_t *out_len);
+int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
+                                   const unsigned char *end, size_t *out_len );
 
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
 /* Get handshake transcript */
 int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
                                           const mbedtls_md_type_t md,
@@ -1812,5 +1812,188 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED ||
           MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+/*
+ * Return supported signature algorithms.
+ *
+ * In future, invocations can be changed to ssl->conf->sig_algs when
+ * mbedtls_ssl_conf_sig_hashes() is deleted.
+ *
+ * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS
+ * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been
+ * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has
+ * been more recently invoked.
+ *
+ */
+static inline const void *mbedtls_ssl_get_sig_algs(
+                                                const mbedtls_ssl_context *ssl )
+{
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if( ssl->handshake != NULL && ssl->handshake->sig_algs != NULL )
+        return( ssl->handshake->sig_algs );
+#endif
+    return( ssl->conf->sig_algs );
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+    ((void) ssl);
+    return( NULL );
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+static inline int mbedtls_ssl_sig_alg_is_offered( const mbedtls_ssl_context *ssl,
+                                                  uint16_t proposed_sig_alg )
+{
+    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs( ssl );
+    if( sig_alg == NULL )
+        return( 0 );
+
+    for( ; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++ )
+    {
+        if( *sig_alg == proposed_sig_alg )
+            return( 1 );
+    }
+    return( 0 );
+}
+
+
+static inline int mbedtls_ssl_sig_alg_is_supported(
+                                                const mbedtls_ssl_context *ssl,
+                                                const uint16_t sig_alg )
+{
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3)
+    {
+        /* High byte is hash */
+        unsigned char hash = MBEDTLS_BYTE_1( sig_alg );
+        unsigned char sig = MBEDTLS_BYTE_0( sig_alg );
+
+        switch( hash )
+        {
+#if defined(MBEDTLS_MD5_C)
+            case MBEDTLS_SSL_HASH_MD5:
+                break;
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+            case MBEDTLS_SSL_HASH_SHA1:
+                break;
+#endif
+
+#if defined(MBEDTLS_SHA224_C)
+            case MBEDTLS_SSL_HASH_SHA224:
+                break;
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+            case MBEDTLS_SSL_HASH_SHA256:
+                break;
+#endif
+
+#if defined(MBEDTLS_SHA384_C)
+            case MBEDTLS_SSL_HASH_SHA384:
+                break;
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+            case MBEDTLS_SSL_HASH_SHA512:
+                break;
+#endif
+
+            default:
+                return( 0 );
+        }
+
+        switch( sig )
+        {
+#if defined(MBEDTLS_RSA_C)
+            case MBEDTLS_SSL_SIG_RSA:
+                break;
+#endif
+
+#if defined(MBEDTLS_ECDSA_C)
+            case MBEDTLS_SSL_SIG_ECDSA:
+                break;
+#endif
+
+        default:
+            return( 0 );
+        }
+
+        return( 1 );
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4)
+    {
+        switch( sig_alg )
+        {
+#if defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \
+    defined(MBEDTLS_ECDSA_C)
+            case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:
+                break;
+#endif /* MBEDTLS_SHA256_C &&
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED &&
+          MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_SHA384_C) && \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \
+    defined(MBEDTLS_ECDSA_C)
+            case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:
+                break;
+#endif /* MBEDTLS_SHA384_C &&
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED &&
+          MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_SHA512_C) && \
+    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \
+    defined(MBEDTLS_ECDSA_C)
+            case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:
+                break;
+#endif /* MBEDTLS_SHA512_C &&
+          MBEDTLS_ECP_DP_SECP521R1_ENABLED &&
+          MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+            case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
+                break;
+#endif /* MBEDTLS_SHA256_C &&
+          MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_RSA_C)
+            case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:
+                break;
+#endif /* MBEDTLS_SHA256_C && MBEDTLS_RSA_C*/
+
+            default:
+                return( 0 );
+        }
+
+        return( 1 );
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+    ((void) ssl);
+    ((void) sig_alg);
+    return( 0 );
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_RSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA), \
+                                    (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
+#elif defined(MBEDTLS_ECDSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA),
+#elif defined(MBEDTLS_RSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
+#else
+#define MBEDTLS_SSL_SIG_ALG( hash )
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_RSA_C */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #endif /* ssl_misc.h */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index a8b1e7d..f189e1d 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -239,9 +239,9 @@
  * This needs to be done at a later stage.
  *
  */
-static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
-                                               const unsigned char *buf,
-                                               size_t len )
+static int ssl_parse_sig_alg_ext( mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  size_t len )
 {
     size_t sig_alg_list_size;
 
@@ -296,7 +296,8 @@
             continue;
         }
 
-        if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 )
+        if( mbedtls_ssl_sig_alg_is_offered(
+                ssl, MBEDTLS_GET_UINT16_BE( p, 0 ) ) )
         {
             mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur );
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
@@ -1674,7 +1675,7 @@
             case MBEDTLS_TLS_EXT_SIG_ALG:
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
 
-                ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
+                ret = ssl_parse_sig_alg_ext( ssl, ext + 4, ext_size );
                 if( ret != 0 )
                     return( ret );
 
@@ -1802,12 +1803,16 @@
      */
     if( sig_hash_alg_ext_present == 0 )
     {
-        mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1;
+        uint16_t sig_algs[] = { MBEDTLS_SSL_SIG_ALG(MBEDTLS_SSL_HASH_SHA1) };
+        mbedtls_md_type_t md_default = MBEDTLS_MD_NONE;
+        for( i = 0; i < sizeof( sig_algs ) / sizeof( sig_algs[0] ) ; i++ )
+        {
+            if( mbedtls_ssl_sig_alg_is_offered( ssl, sig_algs[ i ] ) )
+                md_default = MBEDTLS_MD_SHA1;
+        }
 
-        if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 )
-            md_default = MBEDTLS_MD_NONE;
-
-        mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default );
+        mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs,
+                                             md_default );
     }
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
@@ -2793,26 +2798,24 @@
      */
     if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
     {
-        const int *cur;
-
         /*
          * Supported signature algorithms
          */
-        for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
-        {
-            unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur );
+        const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs( ssl );
+        if( sig_alg == NULL )
+            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
 
-            if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) )
+        for( ; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++ )
+        {
+            unsigned char hash = MBEDTLS_BYTE_1( *sig_alg );
+
+            if( mbedtls_ssl_set_calc_verify_md( ssl, hash ) )
+                continue;
+            if( ! mbedtls_ssl_sig_alg_is_supported( ssl, *sig_alg ) )
                 continue;
 
-#if defined(MBEDTLS_RSA_C)
-            p[2 + sa_len++] = hash;
-            p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-            p[2 + sa_len++] = hash;
-            p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
+            MBEDTLS_PUT_UINT16_BE( *sig_alg, p, sa_len );
+            sa_len += 2;
         }
 
         MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 40d21b5..5e8b60b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -25,13 +25,17 @@
 
 #if defined(MBEDTLS_SSL_TLS_C)
 
+#include <assert.h>
+
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
 #include <stdlib.h>
+#include <stdio.h>
 #define mbedtls_calloc    calloc
 #define mbedtls_free      free
-#endif
+#define mbedtls_printf    printf
+#endif /* !MBEDTLS_PLATFORM_C */
 
 #include "mbedtls/ssl.h"
 #include "ssl_misc.h"
@@ -3150,6 +3154,74 @@
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_ECP_C */
 
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    /* Heap allocate and translate sig_hashes from internal hash identifiers to
+       signature algorithms IANA identifiers.  */
+    if ( mbedtls_ssl_conf_is_tls12_only( ssl->conf ) &&
+         ssl->conf->sig_hashes != NULL )
+    {
+        const int *md;
+        const int *sig_hashes = ssl->conf->sig_hashes;
+        size_t sig_algs_len = 0;
+        uint16_t *p;
+
+#if defined(static_assert)
+        static_assert( MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN
+                       <= ( SIZE_MAX - ( 2 * sizeof(uint16_t) ) ),
+                       "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big" );
+#endif
+
+        for( md = sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
+        {
+            if( mbedtls_ssl_hash_from_md_alg( *md ) == MBEDTLS_SSL_HASH_NONE )
+                continue;
+#if defined(MBEDTLS_ECDSA_C)
+            sig_algs_len += sizeof( uint16_t );
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+            sig_algs_len += sizeof( uint16_t );
+#endif
+            if( sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN )
+                return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+        }
+
+        if( sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN )
+            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+        ssl->handshake->sig_algs = mbedtls_calloc( 1, sig_algs_len +
+                                                      sizeof( uint16_t ));
+        if( ssl->handshake->sig_algs == NULL )
+            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+
+        p = (uint16_t *)ssl->handshake->sig_algs;
+        for( md = sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
+        {
+            unsigned char hash = mbedtls_ssl_hash_from_md_alg( *md );
+            if( hash == MBEDTLS_SSL_HASH_NONE )
+                continue;
+#if defined(MBEDTLS_ECDSA_C)
+            *p = (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA);
+            p++;
+#endif
+#if defined(MBEDTLS_RSA_C)
+            *p = (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA);
+            p++;
+#endif
+        }
+        *p = MBEDTLS_TLS1_3_SIG_NONE;
+        ssl->handshake->sig_algs_heap_allocated = 1;
+    }
+    else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    {
+        ssl->handshake->sig_algs = ssl->conf->sig_algs;
+        ssl->handshake->sig_algs_heap_allocated = 0;
+    }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
     return( 0 );
 }
 
@@ -3991,6 +4063,7 @@
 #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
 /*
  * Set allowed/preferred hashes for handshake signatures
  */
@@ -3999,15 +4072,17 @@
 {
     conf->sig_hashes = hashes;
 }
+#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-/* Configure allowed signature algorithms for use in TLS 1.3 */
+/* Configure allowed signature algorithms for handshake */
 void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf,
                                 const uint16_t* sig_algs )
 {
-    conf->tls13_sig_algs = sig_algs;
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    conf->sig_hashes = NULL;
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+    conf->sig_algs = sig_algs;
 }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_ECP_C)
@@ -5498,6 +5573,15 @@
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_ECP_C */
 
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if ( ssl->handshake->sig_algs_heap_allocated )
+        mbedtls_free( (void*) handshake->sig_algs );
+    handshake->sig_algs = NULL;
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
     {
@@ -6335,6 +6419,7 @@
 }
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /* The selection should be the same as mbedtls_x509_crt_profile_default in
  * x509_crt.c. Here, the order matters. Currently we favor stronger hashes,
  * for no fundamental reason.
@@ -6352,7 +6437,8 @@
 #endif
     MBEDTLS_MD_NONE
 };
-#endif
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 /* The selection should be the same as mbedtls_x509_crt_profile_default in
  * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters:
@@ -6395,57 +6481,112 @@
 };
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 static int ssl_preset_suiteb_hashes[] = {
+#if defined(MBEDTLS_SHA256_C)
     MBEDTLS_MD_SHA256,
+#endif
+#if defined(MBEDTLS_SHA384_C)
     MBEDTLS_MD_SHA384,
+#endif
     MBEDTLS_MD_NONE
 };
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/* NOTICE:
+ *   For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following
+ *   rules SHOULD be upheld.
+ *   - No duplicate entries.
+ *   - But if there is a good reason, do not change the order of the algorithms.
+ *   - ssl_tls12_present* is for TLS 1.2 use only.
+ *   - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.
+ */
 static uint16_t ssl_preset_default_sig_algs[] = {
-    /* ECDSA algorithms */
-#if defined(MBEDTLS_ECDSA_C)
-#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+
+#if defined(MBEDTLS_ECDSA_C) &&  defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
     MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
-#endif /* MBEDTLS_SHA256_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_SHA256_C &&
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA384_C) && \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
     MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
-#endif /* MBEDTLS_SHA384_C && MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_SHA384_C &&
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA512_C) && \
+    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
     MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
-#endif /* MBEDTLS_SHA512_C && MBEDTLS_ECP_DP_SECP521R1_ENABLED */
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_SHA384_C &&
+          MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
-    /* RSA algorithms */
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_SHA256_C)
     MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
-#endif
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_RSA_C) &&  defined(MBEDTLS_SHA256_C)
     MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
 
     MBEDTLS_TLS1_3_SIG_NONE
 };
 
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_default_sig_algs[] = {
+#if defined(MBEDTLS_SHA512_C)
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA512 )
+#endif
+#if defined(MBEDTLS_SHA384_C)
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA384 )
+#endif
+#if defined(MBEDTLS_SHA256_C)
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA256 )
+#endif
+    MBEDTLS_TLS1_3_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+/* NOTICE: see above */
 static uint16_t ssl_preset_suiteb_sig_algs[] = {
-    /* ECDSA algorithms */
-#if defined(MBEDTLS_ECDSA_C)
-#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
-#endif /* MBEDTLS_SHA256_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
-#endif /* MBEDTLS_SHA384_C && MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-#endif /* MBEDTLS_ECDSA_C */
 
-    /* RSA algorithms */
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+#if defined(MBEDTLS_ECDSA_C) &&  defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_SHA256_C &&
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_SHA384_C) && \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_SHA384_C &&
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_SHA256_C)
     MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
-#endif
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_RSA_C) &&  defined(MBEDTLS_SHA256_C)
     MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
 
     MBEDTLS_TLS1_3_SIG_NONE
 };
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {
+#if defined(MBEDTLS_SHA256_C)
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA256 )
 #endif
+#if defined(MBEDTLS_SHA384_C)
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA384 )
+#endif
+    MBEDTLS_TLS1_3_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 static uint16_t ssl_preset_suiteb_groups[] = {
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
@@ -6457,6 +6598,31 @@
     MBEDTLS_SSL_IANA_TLS_GROUP_NONE
 };
 
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
+ * to make sure there are no duplicated signature algorithm entries. */
+static int ssl_check_no_sig_alg_duplication( uint16_t * sig_algs )
+{
+    size_t i, j;
+    int ret = 0;
+
+    for( i = 0; sig_algs[i] != MBEDTLS_TLS1_3_SIG_NONE; i++ )
+    {
+        for( j = 0; j < i; j++ )
+        {
+            if( sig_algs[i] != sig_algs[j] )
+                continue;
+            mbedtls_printf( " entry(%04x,%" MBEDTLS_PRINTF_SIZET
+                            ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n",
+                            sig_algs[i], j, i );
+            ret = -1;
+        }
+    }
+    return( ret );
+}
+
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
 /*
  * Load default in mbedtls_ssl_config
  */
@@ -6467,6 +6633,34 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
 
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    if( ssl_check_no_sig_alg_duplication( ssl_preset_suiteb_sig_algs ) )
+    {
+        mbedtls_printf( "ssl_preset_suiteb_sig_algs has duplicated entries\n" );
+        return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+    }
+
+    if( ssl_check_no_sig_alg_duplication( ssl_preset_default_sig_algs ) )
+    {
+        mbedtls_printf( "ssl_preset_default_sig_algs has duplicated entries\n" );
+        return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if( ssl_check_no_sig_alg_duplication( ssl_tls12_preset_suiteb_sig_algs ) )
+    {
+        mbedtls_printf( "ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n" );
+        return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+    }
+
+    if( ssl_check_no_sig_alg_duplication( ssl_tls12_preset_default_sig_algs ) )
+    {
+        mbedtls_printf( "ssl_tls12_preset_default_sig_algs has duplicated entries\n" );
+        return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
     /* Use the functions here so that they are covered in tests,
      * but otherwise access member directly for efficiency */
     mbedtls_ssl_conf_endpoint( conf, endpoint );
@@ -6563,10 +6757,15 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
             conf->sig_hashes = ssl_preset_suiteb_hashes;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-            conf->tls13_sig_algs = ssl_preset_suiteb_sig_algs;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if( mbedtls_ssl_conf_is_tls12_only( conf ) )
+                conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;
+            else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+                conf->sig_algs = ssl_preset_suiteb_sig_algs;
 #endif
 
 #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -6601,10 +6800,15 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
             conf->sig_hashes = ssl_preset_default_hashes;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-            conf->tls13_sig_algs = ssl_preset_default_sig_algs;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if( mbedtls_ssl_conf_is_tls12_only( conf ) )
+                conf->sig_algs = ssl_tls12_preset_default_sig_algs;
+            else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+                conf->sig_algs = ssl_preset_default_sig_algs;
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -6850,27 +7054,6 @@
 }
 #endif /* MBEDTLS_ECP_C */
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-/*
- * Check if a hash proposed by the peer is in our list.
- * Return 0 if we're willing to use it, -1 otherwise.
- */
-int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
-                                mbedtls_md_type_t md )
-{
-    const int *cur;
-
-    if( ssl->conf->sig_hashes == NULL )
-        return( -1 );
-
-    for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
-        if( *cur == (int) md )
-            return( 0 );
-
-    return( -1 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
                           const mbedtls_ssl_ciphersuite_t *ciphersuite,
@@ -7328,4 +7511,108 @@
           MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+/*
+ * Function for writing a signature algorithm extension.
+ *
+ * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`
+ * value (TLS 1.3 RFC8446):
+ *      enum {
+ *         ....
+ *        ecdsa_secp256r1_sha256( 0x0403 ),
+ *        ecdsa_secp384r1_sha384( 0x0503 ),
+ *        ecdsa_secp521r1_sha512( 0x0603 ),
+ *         ....
+ *      } SignatureScheme;
+ *
+ *      struct {
+ *         SignatureScheme supported_signature_algorithms<2..2^16-2>;
+ *      } SignatureSchemeList;
+ *
+ * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`
+ * value (TLS 1.2 RFC5246):
+ *      enum {
+ *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *          sha512(6), (255)
+ *      } HashAlgorithm;
+ *
+ *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *        SignatureAlgorithm;
+ *
+ *      struct {
+ *          HashAlgorithm hash;
+ *          SignatureAlgorithm signature;
+ *      } SignatureAndHashAlgorithm;
+ *
+ *      SignatureAndHashAlgorithm
+ *        supported_signature_algorithms<2..2^16-2>;
+ *
+ * The TLS 1.3 signature algorithm extension was defined to be a compatible
+ * generalization of the TLS 1.2 signature algorithm extension.
+ * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by
+ * `SignatureScheme` field of TLS 1.3
+ *
+ */
+int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
+                                   const unsigned char *end, size_t *out_len )
+{
+    unsigned char *p = buf;
+    unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */
+    size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding signature_algorithms extension" ) );
+
+    /* Check if we have space for header and length field:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - supported_signature_algorithms_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
+    p += 6;
+
+    /*
+     * Write supported_signature_algorithms
+     */
+    supported_sig_alg = p;
+    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs( ssl );
+    if( sig_alg == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    for( ; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++ )
+    {
+        if( ! mbedtls_ssl_sig_alg_is_supported( ssl, *sig_alg ) )
+            continue;
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
+        MBEDTLS_PUT_UINT16_BE( *sig_alg, p, 0 );
+        p += 2;
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "signature scheme [%x]", *sig_alg ) );
+    }
+
+    /* Length of supported_signature_algorithms */
+    supported_sig_alg_len = p - supported_sig_alg;
+    if( supported_sig_alg_len == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "No signature algorithms defined." ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, buf, 0 );
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len + 2, buf, 2 );
+    /* Write length of supported_signature_algorithms */
+    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len, buf, 4 );
+
+    /* Output the total length of signature algorithms extension. */
+    *out_len = p - buf;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+    return( 0 );
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 9f9ab72..d046495 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -630,7 +630,7 @@
             return( ret );
         p += output_len;
 
-        ret = mbedtls_ssl_tls13_write_sig_alg_ext( ssl, p, end, &output_len );
+        ret = mbedtls_ssl_write_sig_alg_ext( ssl, p, end, &output_len );
         if( ret != 0 )
             return( ret );
         p += output_len;
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index c789ed4..a87af94 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -136,80 +136,6 @@
 }
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-
-/*
- * mbedtls_ssl_tls13_write_sig_alg_ext( )
- *
- * enum {
- *    ....
- *   ecdsa_secp256r1_sha256( 0x0403 ),
- *   ecdsa_secp384r1_sha384( 0x0503 ),
- *   ecdsa_secp521r1_sha512( 0x0603 ),
- *    ....
- * } SignatureScheme;
- *
- * struct {
- *    SignatureScheme supported_signature_algorithms<2..2^16-2>;
- * } SignatureSchemeList;
- *
- * Only if we handle at least one key exchange that needs signatures.
- */
-int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         unsigned char *end,
-                                         size_t *out_len )
-{
-    unsigned char *p = buf;
-    unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */
-    size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */
-
-    *out_len = 0;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding signature_algorithms extension" ) );
-
-    /* Check if we have space for header and length field:
-     * - extension_type         (2 bytes)
-     * - extension_data_length  (2 bytes)
-     * - supported_signature_algorithms_length   (2 bytes)
-     */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
-    p += 6;
-
-    /*
-     * Write supported_signature_algorithms
-     */
-    supported_sig_alg = p;
-    for( const uint16_t *sig_alg = ssl->conf->tls13_sig_algs;
-         *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++ )
-    {
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        MBEDTLS_PUT_UINT16_BE( *sig_alg, p, 0 );
-        p += 2;
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "signature scheme [%x]", *sig_alg ) );
-    }
-
-    /* Length of supported_signature_algorithms */
-    supported_sig_alg_len = p - supported_sig_alg;
-    if( supported_sig_alg_len == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "No signature algorithms defined." ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    /* Write extension_type */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, buf, 0 );
-    /* Write extension_data_length */
-    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len + 2, buf, 2 );
-    /* Write length of supported_signature_algorithms */
-    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len, buf, 4 );
-
-    /* Output the total length of signature algorithms extension. */
-    *out_len = p - buf;
-
-    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG;
-    return( 0 );
-}
-
 /*
  * STATE HANDLING: Read CertificateVerify
  */
@@ -283,19 +209,6 @@
     *verify_buffer_len = idx;
 }
 
-static int ssl_tls13_sig_alg_is_offered( const mbedtls_ssl_context *ssl,
-                                         uint16_t sig_alg )
-{
-    const uint16_t *tls13_sig_alg = ssl->conf->tls13_sig_algs;
-
-    for( ; *tls13_sig_alg != MBEDTLS_TLS1_3_SIG_NONE ; tls13_sig_alg++ )
-    {
-        if( *tls13_sig_alg == sig_alg )
-            return( 1 );
-    }
-    return( 0 );
-}
-
 static int ssl_tls13_parse_certificate_verify( mbedtls_ssl_context *ssl,
                                                const unsigned char *buf,
                                                const unsigned char *end,
@@ -340,7 +253,7 @@
      *
      * Check if algorithm is an offered signature algorithm.
      */
-    if( ! ssl_tls13_sig_alg_is_offered( ssl, algorithm ) )
+    if( ! mbedtls_ssl_sig_alg_is_offered( ssl, algorithm ) )
     {
         /* algorithm not in offered signature algorithms list */
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Received signature algorithm(%04x) is not "
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 762e21b..1de8ce3 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -1729,7 +1729,7 @@
     {
         crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 );
         mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test );
-        mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test );
+        mbedtls_ssl_conf_sig_algs( &conf, ssl_sig_algs_for_test );
     }
 
     if( opt.context_crt_cb == 0 )
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index f627274..388ffe0 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -2586,7 +2586,7 @@
     {
         crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 );
         mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test );
-        mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test );
+        mbedtls_ssl_conf_sig_algs( &conf, ssl_sig_algs_for_test );
     }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
diff --git a/programs/ssl/ssl_test_common_source.c b/programs/ssl/ssl_test_common_source.c
index 62cd35d..0e66895 100644
--- a/programs/ssl/ssl_test_common_source.c
+++ b/programs/ssl/ssl_test_common_source.c
@@ -262,24 +262,34 @@
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-int ssl_sig_hashes_for_test[] = {
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_RSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA), \
+                                    (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
+#elif defined(MBEDTLS_ECDSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA),
+#elif defined(MBEDTLS_RSA_C)
+#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
+#else
+#define MBEDTLS_SSL_SIG_ALG( hash )
+#endif
+uint16_t ssl_sig_algs_for_test[] = {
 #if defined(MBEDTLS_SHA512_C)
-    MBEDTLS_MD_SHA512,
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA512 )
 #endif
 #if defined(MBEDTLS_SHA384_C)
-    MBEDTLS_MD_SHA384,
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA384 )
 #endif
 #if defined(MBEDTLS_SHA256_C)
-    MBEDTLS_MD_SHA256,
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA256 )
 #endif
 #if defined(MBEDTLS_SHA224_C)
-    MBEDTLS_MD_SHA224,
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA224 )
 #endif
 #if defined(MBEDTLS_SHA1_C)
     /* Allow SHA-1 as we use it extensively in tests. */
-    MBEDTLS_MD_SHA1,
+    MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA1 )
 #endif
-    MBEDTLS_MD_NONE
+    MBEDTLS_TLS1_3_SIG_NONE
 };
 #endif /* MBEDTLS_X509_CRT_PARSE_C */