]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Refactor sigalg handling
authorViktor Dukhovni <openssl-users@dukhovni.org>
Wed, 5 Mar 2025 19:02:28 +0000 (06:02 +1100)
committerAlexandr Nedvedicky <sashan@openssl.org>
Sun, 9 Mar 2025 22:19:37 +0000 (23:19 +0100)
- The default sigalg list now puts ML-DSA-65 first, then ML-DSA-87
  and then ML-DSA-44.  (87 vs. 44 Subject to bikeshedding).

- The mintls and maxtls versions are now taken into account for
  both built-in and provided algorithms.

- Some algorithms have a separate TLSv1.2-specific name for future
  reporting via openssl-list(1).

- ML-DSA aside, any new provided algorithms go at the end of the
  default list (backwards-compatible inclusion).

- The built-in algorithms now also have min/max DTLS versions.
  Though the provider TLS-SIGALG capability was extended to also report
  the DTLS version range, the minimum supported DTLS is 1.3, which we
  don't yet have, so it is not yet possible to add DTLS sigalgs via a
  provider

- The TLS 1.3 brainpool sigalgs got their correct IANA names, with
  the legacy names as purported TLS 1.2 alternatives, but since
  these are for TLS 1.3 and up those names are for matching only,
  the reported value will still be the 1.3 name.

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26975)

.github/workflows/ci.yml
doc/man7/provider-base.pod
providers/common/capabilities.c
ssl/ssl_local.h
ssl/t1_lib.c
test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt
test/recipes/75-test_quicapi_data/ssltraceref.txt
test/recipes/95-test_external_tlsfuzzer_data/cert.json.in
util/perl/OpenSSL/paramnames.pm

index 17e2104a52ab16ed8efd66b74b99b5d833d36527..09cc0baa86f252eccd3ca84c06ba943859901de1 100644 (file)
@@ -659,8 +659,9 @@ jobs:
         ./util/opensslwrap.sh version -c
     - name: test external oqs-provider
       run: make test TESTS="test_external_oqsprovider"
-    - name: test external pkcs11-provider
-      run: make test TESTS="test_external_pkcs11_provider" VERBOSE=1
+    # Disabled temporarily: https://github.com/latchset/pkcs11-provider/pull/525#discussion_r1982805969
+    # - name: test external pkcs11-provider
+    #   run: make test TESTS="test_external_pkcs11_provider" VERBOSE=1
 
   external-tests-pyca:
     runs-on: ubuntu-latest
index a27d948b0855a2d7704dc5e64c85af9c78f67047..f40333be299698a0baae044fbffa0aae7a2ea118 100644 (file)
@@ -759,14 +759,18 @@ This value must be supplied.
 
 =item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS>) <integer>
 
-These parameters can be used to describe the minimum and maximum TLS
+=item "tls-min-dtls" (B<OSSL_CAPABILITY_TLS_SIGALG_MIN_DTLS>) <integer>
+
+=item "tls-max-dtls" (B<OSSL_CAPABILITY_TLS_SIGALG_MAX_DTLS>) <integer>
+
+These parameters can be used to describe the minimum and maximum TLS and DTLS
 versions supported by the signature algorithm. The values equate to the
 on-the-wire encoding of the various TLS versions. For example TLSv1.3 is
 0x0304 (772 decimal), and TLSv1.2 is 0x0303 (771 decimal). A 0 indicates that
-there is no defined minimum or maximum. A -1 indicates that the signature
-algorithm should not be used in that protocol.
-Presently values representing anything other than TLS1.3 mean that the
-complete algorithm is ignored.
+there is no defined minimum or maximum. A -1 in either the min or max field
+indicates that the signature algorithm should not be used in that protocol.
+Presently, provider signature algorithms are used only with TLS 1.3, if
+that's enclosed in the specified range.
 
 =back
 
index 2a68f1b12cca869a3c1ede44f43c3da05ee93c63..d5222aa7b5894117c54ca7c4d39ae383a5cc441d 100644 (file)
@@ -280,12 +280,14 @@ typedef struct tls_sigalg_constants_st {
     unsigned int sec_bits;    /* Bits of security */
     int min_tls;              /* Minimum TLS version, -1 unsupported */
     int max_tls;              /* Maximum TLS version (or 0 for undefined) */
+    int min_dtls;             /* Minimum DTLS version, -1 unsupported */
+    int max_dtls;             /* Maximum DTLS version (or 0 for undefined) */
 } TLS_SIGALG_CONSTANTS;
 
 static const TLS_SIGALG_CONSTANTS sigalg_constants_list[3] = {
-    { 0x0904, 128, TLS1_3_VERSION, 0 },
-    { 0x0905, 192, TLS1_3_VERSION, 0 },
-    { 0x0906, 256, TLS1_3_VERSION, 0 },
+    { 0x0904, 128, TLS1_3_VERSION, 0, -1, -1 },
+    { 0x0905, 192, TLS1_3_VERSION, 0, -1, -1 },
+    { 0x0906, 256, TLS1_3_VERSION, 0, -1, -1 },
 };
 
 # define TLS_SIGALG_ENTRY(tlsname, algorithm, oid, idx)                         \
@@ -304,10 +306,14 @@ static const TLS_SIGALG_CONSTANTS sigalg_constants_list[3] = {
                        (unsigned int *)&sigalg_constants_list[idx].min_tls),    \
         OSSL_PARAM_int(OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS,                      \
                        (unsigned int *)&sigalg_constants_list[idx].max_tls),    \
+        OSSL_PARAM_int(OSSL_CAPABILITY_TLS_SIGALG_MIN_DTLS,                     \
+                       (unsigned int *)&sigalg_constants_list[idx].min_dtls),   \
+        OSSL_PARAM_int(OSSL_CAPABILITY_TLS_SIGALG_MAX_DTLS,                     \
+                       (unsigned int *)&sigalg_constants_list[idx].max_dtls),   \
         OSSL_PARAM_END                                                          \
     }
 
-static const OSSL_PARAM param_sigalg_list[][8] = {
+static const OSSL_PARAM param_sigalg_list[][10] = {
     TLS_SIGALG_ENTRY("mldsa44", "ML-DSA-44", "2.16.840.1.101.3.4.3.17", 0),
     TLS_SIGALG_ENTRY("mldsa65", "ML-DSA-65", "2.16.840.1.101.3.4.3.18", 1),
     TLS_SIGALG_ENTRY("mldsa87", "ML-DSA-87", "2.16.840.1.101.3.4.3.19", 2),
index 3cebc1c50695d85fbb4a7ff10d744920968dbd2b..eeb55bd74e1be2ff0328d9ab3275ec7267046420 100644 (file)
 # define SSL_CONNECTION_IS_DTLS(s) \
     (SSL_CONNECTION_GET_SSL(s)->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
 
+/* Check if an SSL_CTX structure is using DTLS */
+# define SSL_CTX_IS_DTLS(ctx) \
+    (ctx->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
+
 /* Check if we are using TLSv1.3 */
 # define SSL_CONNECTION_IS_TLS13(s) (!SSL_CONNECTION_IS_DTLS(s) \
     && SSL_CONNECTION_GET_SSL(s)->method->version >= TLS1_3_VERSION \
@@ -772,6 +776,8 @@ typedef struct tls_sigalg_info_st {
     unsigned int secbits;    /* Bits of security (from SP800-57) */
     int mintls;              /* Minimum TLS version, -1 unsupported */
     int maxtls;              /* Maximum TLS version (or 0 for undefined) */
+    int mindtls;             /* Minimum DTLS version, -1 unsupported */
+    int maxdtls;             /* Maximum DTLS version (or 0 for undefined) */
 } TLS_SIGALG_INFO;
 
 /*
@@ -1169,6 +1175,7 @@ struct ssl_ctx_st {
     const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX];
     size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
 
+    size_t sigalg_lookup_cache_len;
     size_t tls12_sigalgs_len;
     /* Cache of all sigalgs we know and whether they are available or not */
     struct sigalg_lookup_st *sigalg_lookup_cache;
@@ -1875,6 +1882,8 @@ struct ssl_connection_st {
 typedef struct sigalg_lookup_st {
     /* TLS 1.3 signature scheme name */
     const char *name;
+    /* TLS 1.2 signature scheme name */
+    const char *name12;
     /* Raw value used in extension */
     uint16_t sigalg;
     /* NID of hash algorithm or NID_undef if no hash */
@@ -1890,7 +1899,14 @@ typedef struct sigalg_lookup_st {
     /* Required public key curve (ECDSA only) */
     int curve;
     /* Whether this signature algorithm is actually available for use */
-    int enabled;
+    int available;
+    /* Whether this signature algorithm is by default advertised */
+    int advertise;
+    /* Supported protocol ranges */
+    int mintls;
+    int maxtls;
+    int mindtls;
+    int maxdtls;
 } SIGALG_LOOKUP;
 
 /* DTLS structures */
@@ -2231,6 +2247,9 @@ typedef enum downgrade_en {
 #define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256              0x081a
 #define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384              0x081b
 #define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512              0x081c
+#define TLSEXT_SIGALG_mldsa44                                   0x0904
+#define TLSEXT_SIGALG_mldsa65                                   0x0905
+#define TLSEXT_SIGALG_mldsa87                                   0x0906
 
 /* Sigalgs names */
 #define TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name                    "ecdsa_secp256r1_sha256"
@@ -2254,17 +2273,25 @@ typedef enum downgrade_en {
 #define TLSEXT_SIGALG_dsa_sha512_name                                "dsa_sha512"
 #define TLSEXT_SIGALG_dsa_sha224_name                                "dsa_sha224"
 #define TLSEXT_SIGALG_dsa_sha1_name                                  "dsa_sha1"
-#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_name               "gost2012_256"
-#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_name               "gost2012_512"
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_name               "gostr34102012_256"
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_name               "gostr34102012_512"
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias              "gost2012_256"
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_alias              "gost2012_512"
 #define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name       "gost2012_256"
 #define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name       "gost2012_512"
 #define TLSEXT_SIGALG_gostr34102001_gostr3411_name                   "gost2001_gost94"
 
 #define TLSEXT_SIGALG_ed25519_name                                   "ed25519"
 #define TLSEXT_SIGALG_ed448_name                                     "ed448"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name              "ecdsa_brainpoolP256r1_sha256"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name              "ecdsa_brainpoolP384r1_sha384"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name              "ecdsa_brainpoolP512r1_sha512"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name              "ecdsa_brainpoolP256r1tls13_sha256"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name              "ecdsa_brainpoolP384r1tls13_sha384"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name              "ecdsa_brainpoolP512r1tls13_sha512"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_alias             "ecdsa_brainpoolP256r1_sha256"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_alias             "ecdsa_brainpoolP384r1_sha384"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_alias             "ecdsa_brainpoolP512r1_sha512"
+#define TLSEXT_SIGALG_mldsa44_name                                   "mldsa44"
+#define TLSEXT_SIGALG_mldsa65_name                                   "mldsa65"
+#define TLSEXT_SIGALG_mldsa87_name                                   "mldsa87"
 
 /* Known PSK key exchange modes */
 #define TLSEXT_KEX_MODE_KE                                      0x00
index 456d98cb4335710315ede46c2844d7a141085a76..d9f24fe7ea4c28f057ab4f78ea12c775ae7f7001 100644 (file)
@@ -525,19 +525,33 @@ static int add_provider_sigalgs(const OSSL_PARAM params[], void *data)
             goto err;
     }
 
-    /* The remaining parameters below are mandatory again */
-    p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS);
-    if (p == NULL || !OSSL_PARAM_get_int(p, &sinf->mintls)) {
+    /* Optional, not documented prior to 3.5 */
+    sinf->mindtls = sinf->maxdtls = -1;
+    p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MIN_DTLS);
+    if (p != NULL && !OSSL_PARAM_get_int(p, &sinf->mindtls)) {
         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
         goto err;
     }
-    if ((sinf->mintls != 0) && (sinf->mintls != -1) &&
-        ((sinf->mintls < TLS1_3_VERSION))) {
-        /* ignore this sigalg as this OpenSSL doesn't know how to handle it */
-        ret = 1;
+    p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MAX_DTLS);
+    if (p != NULL && !OSSL_PARAM_get_int(p, &sinf->maxdtls)) {
+        ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
         goto err;
     }
+    /* DTLS version numbers grow downward */
+    if ((sinf->maxdtls != 0) && (sinf->maxdtls != -1) &&
+        ((sinf->maxdtls > sinf->mindtls))) {
+        ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+        goto err;
+    }
+    /* No provider sigalgs are supported in DTLS, reset after checking. */
+    sinf->mindtls = sinf->maxdtls = -1;
 
+    /* The remaining parameters below are mandatory again */
+    p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS);
+    if (p == NULL || !OSSL_PARAM_get_int(p, &sinf->mintls)) {
+        ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
+        goto err;
+    }
     p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS);
     if (p == NULL || !OSSL_PARAM_get_int(p, &sinf->maxtls)) {
         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
@@ -548,9 +562,15 @@ static int add_provider_sigalgs(const OSSL_PARAM params[], void *data)
         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
         goto err;
     }
+    if ((sinf->mintls != 0) && (sinf->mintls != -1) &&
+        ((sinf->mintls > TLS1_3_VERSION)))
+        sinf->mintls = sinf->maxtls = -1;
     if ((sinf->maxtls != 0) && (sinf->maxtls != -1) &&
-        ((sinf->maxtls < TLS1_3_VERSION))) {
-        /* ignore this sigalg as this OpenSSL doesn't know how to handle it */
+        ((sinf->maxtls < TLS1_3_VERSION)))
+        sinf->mintls = sinf->maxtls = -1;
+
+    /* Ignore unusable sigalgs */
+    if (sinf->mintls == -1 && sinf->mindtls == -1) {
         ret = 1;
         goto err;
     }
@@ -1892,6 +1912,9 @@ int tls1_check_ec_tmp_key(SSL_CONNECTION *s, unsigned long cid)
 
 /* Default sigalg schemes */
 static const uint16_t tls12_sigalgs[] = {
+    TLSEXT_SIGALG_mldsa65,
+    TLSEXT_SIGALG_mldsa87,
+    TLSEXT_SIGALG_mldsa44,
     TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
     TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
     TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
@@ -1941,113 +1964,191 @@ static const uint16_t suiteb_sigalgs[] = {
 };
 
 static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
-    {TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name, TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
+    {TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name,
+     "ECDSA+SHA256", TLSEXT_SIGALG_ecdsa_secp256r1_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1},
-    {TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name, TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
+     NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name,
+     "ECDSA+SHA384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA384, NID_secp384r1, 1},
-    {TLSEXT_SIGALG_ecdsa_secp521r1_sha512_name, TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
+     NID_ecdsa_with_SHA384, NID_secp384r1, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_ecdsa_secp521r1_sha512_name,
+     "ECDSA+SHA512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA512, NID_secp521r1, 1},
-    {TLSEXT_SIGALG_ed25519_name, TLSEXT_SIGALG_ed25519,
+     NID_ecdsa_with_SHA512, NID_secp521r1, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+
+    {TLSEXT_SIGALG_ed25519_name,
+     NULL, TLSEXT_SIGALG_ed25519,
      NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_ed448_name, TLSEXT_SIGALG_ed448,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_ed448_name,
+     NULL, TLSEXT_SIGALG_ed448,
      NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_ecdsa_sha224_name, TLSEXT_SIGALG_ecdsa_sha224,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+
+    {TLSEXT_SIGALG_ecdsa_sha224_name,
+     "ECDSA+SHA224", TLSEXT_SIGALG_ecdsa_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA224, NID_undef, 1},
-    {TLSEXT_SIGALG_ecdsa_sha1_name, TLSEXT_SIGALG_ecdsa_sha1,
+     NID_ecdsa_with_SHA224, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_ecdsa_sha1_name,
+     "ECDSA+SHA1", TLSEXT_SIGALG_ecdsa_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA1, NID_undef, 1},
-    {TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name, TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256,
+     NID_ecdsa_with_SHA1, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+
+    {TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name,
+     TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_alias,
+     TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA256, NID_brainpoolP256r1, 1},
-    {TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name, TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384,
+     NID_ecdsa_with_SHA256, NID_brainpoolP256r1, 1, 0,
+     TLS1_3_VERSION, 0, -1, -1},
+    {TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name,
+     TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_alias,
+     TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA384, NID_brainpoolP384r1, 1},
-    {TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name, TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512,
+     NID_ecdsa_with_SHA384, NID_brainpoolP384r1, 1, 0,
+     TLS1_3_VERSION, 0, -1, -1},
+    {TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name,
+     TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_alias,
+     TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA512, NID_brainpoolP512r1, 1},
-    {TLSEXT_SIGALG_rsa_pss_rsae_sha256_name, TLSEXT_SIGALG_rsa_pss_rsae_sha256,
+     NID_ecdsa_with_SHA512, NID_brainpoolP512r1, 1, 0,
+     TLS1_3_VERSION, 0, -1, -1},
+
+    {TLSEXT_SIGALG_rsa_pss_rsae_sha256_name,
+     "PSS+SHA256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pss_rsae_sha384_name, TLSEXT_SIGALG_rsa_pss_rsae_sha384,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_rsa_pss_rsae_sha384_name,
+     "PSS+SHA384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pss_rsae_sha512_name, TLSEXT_SIGALG_rsa_pss_rsae_sha512,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_rsa_pss_rsae_sha512_name,
+     "PSS+SHA512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pss_pss_sha256_name, TLSEXT_SIGALG_rsa_pss_pss_sha256,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+
+    {TLSEXT_SIGALG_rsa_pss_pss_sha256_name,
+     NULL, TLSEXT_SIGALG_rsa_pss_pss_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pss_pss_sha384_name, TLSEXT_SIGALG_rsa_pss_pss_sha384,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_rsa_pss_pss_sha384_name,
+     NULL, TLSEXT_SIGALG_rsa_pss_pss_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pss_pss_sha512_name, TLSEXT_SIGALG_rsa_pss_pss_sha512,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+    {TLSEXT_SIGALG_rsa_pss_pss_sha512_name,
+     NULL, TLSEXT_SIGALG_rsa_pss_pss_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA_PSS_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pkcs1_sha256_name, TLSEXT_SIGALG_rsa_pkcs1_sha256,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, 0, DTLS1_2_VERSION, 0},
+
+    {TLSEXT_SIGALG_rsa_pkcs1_sha256_name,
+     "RSA+SHA256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha256WithRSAEncryption, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pkcs1_sha384_name, TLSEXT_SIGALG_rsa_pkcs1_sha384,
+     NID_sha256WithRSAEncryption, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha384_name,
+     "RSA+SHA384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha384WithRSAEncryption, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pkcs1_sha512_name, TLSEXT_SIGALG_rsa_pkcs1_sha512,
+     NID_sha384WithRSAEncryption, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha512_name,
+     "RSA+SHA512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha512WithRSAEncryption, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pkcs1_sha224_name, TLSEXT_SIGALG_rsa_pkcs1_sha224,
+     NID_sha512WithRSAEncryption, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+
+    {TLSEXT_SIGALG_rsa_pkcs1_sha224_name,
+     "RSA+SHA224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha224WithRSAEncryption, NID_undef, 1},
-    {TLSEXT_SIGALG_rsa_pkcs1_sha1_name, TLSEXT_SIGALG_rsa_pkcs1_sha1,
+     NID_sha224WithRSAEncryption, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_rsa_pkcs1_sha1_name,
+     "RSA+SHA1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha1WithRSAEncryption, NID_undef, 1},
-    {TLSEXT_SIGALG_dsa_sha256_name, TLSEXT_SIGALG_dsa_sha256,
+     NID_sha1WithRSAEncryption, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+
+    {TLSEXT_SIGALG_dsa_sha256_name,
+     "DSA+SHA256", TLSEXT_SIGALG_dsa_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_dsa_with_SHA256, NID_undef, 1},
-    {TLSEXT_SIGALG_dsa_sha384_name, TLSEXT_SIGALG_dsa_sha384,
+     NID_dsa_with_SHA256, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_dsa_sha384_name,
+     "DSA+SHA384", TLSEXT_SIGALG_dsa_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_dsa_sha512_name, TLSEXT_SIGALG_dsa_sha512,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_dsa_sha512_name,
+     "DSA+SHA512", TLSEXT_SIGALG_dsa_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_dsa_sha224_name, TLSEXT_SIGALG_dsa_sha224,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_dsa_sha224_name,
+     "DSA+SHA224", TLSEXT_SIGALG_dsa_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_dsa_sha1_name, TLSEXT_SIGALG_dsa_sha1,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_dsa_sha1_name,
+     "DSA+SHA1", TLSEXT_SIGALG_dsa_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_dsaWithSHA1, NID_undef, 1},
+     NID_dsaWithSHA1, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+
 #ifndef OPENSSL_NO_GOST
-    {TLSEXT_SIGALG_gostr34102012_256_intrinsic_name, TLSEXT_SIGALG_gostr34102012_256_intrinsic,
+    {TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias, /* RFC9189 */
+     TLSEXT_SIGALG_gostr34102012_256_intrinsic_name,
+     TLSEXT_SIGALG_gostr34102012_256_intrinsic,
      NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
      NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_gostr34102012_512_intrinsic_name, TLSEXT_SIGALG_gostr34102012_512_intrinsic,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias, /* RFC9189 */
+     TLSEXT_SIGALG_gostr34102012_256_intrinsic_name,
+     TLSEXT_SIGALG_gostr34102012_512_intrinsic,
      NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
      NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+
+    {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name,
+     NULL, TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256,
      NID_id_GostR3411_2012_256, SSL_MD_GOST12_256_IDX,
      NID_id_GostR3410_2012_256, SSL_PKEY_GOST12_256,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name,
+     NULL, TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512,
      NID_id_GostR3411_2012_512, SSL_MD_GOST12_512_IDX,
      NID_id_GostR3410_2012_512, SSL_PKEY_GOST12_512,
-     NID_undef, NID_undef, 1},
-    {TLSEXT_SIGALG_gostr34102001_gostr3411_name, TLSEXT_SIGALG_gostr34102001_gostr3411,
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
+    {TLSEXT_SIGALG_gostr34102001_gostr3411_name,
+     NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
      NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
      NID_id_GostR3410_2001, SSL_PKEY_GOST01,
-     NID_undef, NID_undef, 1}
+     NID_undef, NID_undef, 1, 0,
+     TLS1_2_VERSION, TLS1_2_VERSION, DTLS1_2_VERSION, DTLS1_2_VERSION},
 #endif
 };
 /* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
 static const SIGALG_LOOKUP legacy_rsa_sigalg = {
-    "rsa_pkcs1_md5_sha1", 0,
+    "rsa_pkcs1_md5_sha1", NULL, 0,
      NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
      EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_undef, NID_undef, 1
+     NID_undef, NID_undef, 1, 0,
+     TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION
 };
 
 /*
@@ -2068,23 +2169,26 @@ static const uint16_t tls_default_sigalg[] = {
 
 int ssl_setup_sigalgs(SSL_CTX *ctx)
 {
-    size_t i, cache_idx, sigalgs_len;
+    size_t i, cache_idx, sigalgs_len, enabled;
     const SIGALG_LOOKUP *lu;
     SIGALG_LOOKUP *cache = NULL;
     uint16_t *tls12_sigalgs_list = NULL;
     EVP_PKEY *tmpkey = EVP_PKEY_new();
+    int istls;
     int ret = 0;
 
     if (ctx == NULL)
         goto err;
 
+    istls = !SSL_CTX_IS_DTLS(ctx);
+
     sigalgs_len = OSSL_NELEM(sigalg_lookup_tbl) + ctx->sigalg_list_len;
 
-    cache = OPENSSL_malloc(sizeof(const SIGALG_LOOKUP) * sigalgs_len);
+    cache = OPENSSL_zalloc(sizeof(const SIGALG_LOOKUP) * sigalgs_len);
     if (cache == NULL || tmpkey == NULL)
         goto err;
 
-    tls12_sigalgs_list = OPENSSL_malloc(sizeof(uint16_t) * sigalgs_len);
+    tls12_sigalgs_list = OPENSSL_zalloc(sizeof(uint16_t) * sigalgs_len);
     if (tls12_sigalgs_list == NULL)
         goto err;
 
@@ -2095,7 +2199,6 @@ int ssl_setup_sigalgs(SSL_CTX *ctx)
         EVP_PKEY_CTX *pctx;
 
         cache[i] = *lu;
-        tls12_sigalgs_list[i] = tls12_sigalgs[i];
 
         /*
          * Check hash is available.
@@ -2107,18 +2210,18 @@ int ssl_setup_sigalgs(SSL_CTX *ctx)
          */
         if (lu->hash != NID_undef
                 && ctx->ssl_digest_methods[lu->hash_idx] == NULL) {
-            cache[i].enabled = 0;
+            cache[i].available = 0;
             continue;
         }
 
         if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
-            cache[i].enabled = 0;
+            cache[i].available = 0;
             continue;
         }
         pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, tmpkey, ctx->propq);
         /* If unable to create pctx we assume the sig algorithm is unavailable */
         if (pctx == NULL)
-            cache[i].enabled = 0;
+            cache[i].available = 0;
         EVP_PKEY_CTX_free(pctx);
     }
 
@@ -2127,6 +2230,7 @@ int ssl_setup_sigalgs(SSL_CTX *ctx)
     for (i = 0; i < ctx->sigalg_list_len; i++) {
         TLS_SIGALG_INFO si = ctx->sigalg_list[i];
         cache[cache_idx].name = si.name;
+        cache[cache_idx].name12 = si.sigalg_name;
         cache[cache_idx].sigalg = si.code_point;
         tls12_sigalgs_list[cache_idx] = si.code_point;
         cache[cache_idx].hash = si.hash_name?OBJ_txt2nid(si.hash_name):NID_undef;
@@ -2135,14 +2239,46 @@ int ssl_setup_sigalgs(SSL_CTX *ctx)
         cache[cache_idx].sig_idx = i + SSL_PKEY_NUM;
         cache[cache_idx].sigandhash = OBJ_txt2nid(si.sigalg_name);
         cache[cache_idx].curve = NID_undef;
-        /* all provided sigalgs are enabled by load */
-        cache[cache_idx].enabled = 1;
+        cache[cache_idx].mintls = TLS1_3_VERSION;
+        cache[cache_idx].maxtls = TLS1_3_VERSION;
+        cache[cache_idx].mindtls = -1;
+        cache[cache_idx].maxdtls = -1;
+        /* Compatibility with TLS 1.3 is checked on load */
+        cache[cache_idx].available = istls;
+        cache[cache_idx].advertise = 0;
         cache_idx++;
     }
     ERR_pop_to_mark();
+
+    enabled = 0;
+    for (i = 0; i < OSSL_NELEM(tls12_sigalgs); ++i) {
+        SIGALG_LOOKUP *ent = cache;
+        size_t j;
+
+        for (j = 0; j < sigalgs_len; ent++, j++) {
+            if (ent->sigalg != tls12_sigalgs[i])
+                continue;
+            /* Dedup by marking cache entry as default enabled. */
+            if (ent->available && !ent->advertise) {
+                ent->advertise = 1;
+                tls12_sigalgs_list[enabled++] = tls12_sigalgs[i];
+            }
+            break;
+        }
+    }
+
+    /* Append any provider sigalgs not yet handled */
+    for (i = OSSL_NELEM(sigalg_lookup_tbl); i < sigalgs_len; ++i) {
+        SIGALG_LOOKUP *ent = &cache[i];
+
+        if (ent->available && !ent->advertise)
+            tls12_sigalgs_list[enabled++] = ent->sigalg;
+    }
+
     ctx->sigalg_lookup_cache = cache;
+    ctx->sigalg_lookup_cache_len = sigalgs_len;
     ctx->tls12_sigalgs = tls12_sigalgs_list;
-    ctx->tls12_sigalgs_len = sigalgs_len;
+    ctx->tls12_sigalgs_len = enabled;
     cache = NULL;
     tls12_sigalgs_list = NULL;
 
@@ -2230,23 +2366,22 @@ char *SSL_get1_builtin_sigalgs(OSSL_LIB_CTX *libctx)
 }
 
 /* Lookup TLS signature algorithm */
-static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL_CONNECTION *s,
+static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL_CTX *ctx,
                                                uint16_t sigalg)
 {
     size_t i;
-    const SIGALG_LOOKUP *lu;
+    const SIGALG_LOOKUP *lu = ctx->sigalg_lookup_cache;
 
-    for (i = 0, lu = SSL_CONNECTION_GET_CTX(s)->sigalg_lookup_cache;
-         i < SSL_CONNECTION_GET_CTX(s)->tls12_sigalgs_len;
-         lu++, i++) {
+    for (i = 0; i < ctx->sigalg_lookup_cache_len; lu++, i++) {
         if (lu->sigalg == sigalg) {
-            if (!lu->enabled)
+            if (!lu->available)
                 return NULL;
             return lu;
         }
     }
     return NULL;
 }
+
 /* Lookup hash: return 0 if invalid or not enabled */
 int tls1_lookup_md(SSL_CTX *ctx, const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
 {
@@ -2355,7 +2490,9 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL_CONNECTION *s,
         return NULL;
 
     if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, tls_default_sigalg[idx]);
+        const SIGALG_LOOKUP *lu =
+            tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s),
+                               tls_default_sigalg[idx]);
 
         if (lu == NULL)
             return NULL;
@@ -2438,7 +2575,8 @@ int tls_check_sigalg_curve(const SSL_CONNECTION *s, int curve)
     }
 
     for (i = 0; i < siglen; i++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, sigs[i]);
+        const SIGALG_LOOKUP *lu =
+            tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), sigs[i]);
 
         if (lu == NULL)
             continue;
@@ -2518,6 +2656,7 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey)
     int pkeyid = -1;
     const SIGALG_LOOKUP *lu;
     int secbits = 0;
+    int minversion, maxversion;
 
     pkeyid = EVP_PKEY_get_id(pkey);
 
@@ -2531,21 +2670,40 @@ int tls12_check_peer_sigalg(SSL_CONNECTION *s, uint16_t sig, EVP_PKEY *pkey)
         if (pkeyid == EVP_PKEY_RSA)
             pkeyid = EVP_PKEY_RSA_PSS;
     }
-    lu = tls1_lookup_sigalg(s, sig);
+
+    /* Is this code point available and compatible with the protocol */
+    lu = tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), sig);
+    if (lu == NULL) {
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
+        return 0;
+    }
+    minversion = SSL_CONNECTION_IS_DTLS(s) ? lu->mindtls : lu->mintls;
+    maxversion = SSL_CONNECTION_IS_DTLS(s) ? lu->maxdtls : lu->maxtls;
+    if (minversion == -1 || maxversion == -1 || !lu->available
+        || (minversion != 0 && s->max_proto_version != 0
+            && ssl_version_cmp(s, minversion, s->max_proto_version) > 0)
+        || (maxversion != 0 && s->min_proto_version != 0
+            && ssl_version_cmp(s, maxversion, s->min_proto_version) < 0)
+        || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu)) {
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
+        return 0;
+    }
+
     /* if this sigalg is loaded, set so far unknown pkeyid to its sig NID */
-    if ((pkeyid == EVP_PKEY_KEYMGMT) && (lu != NULL))
+    if (pkeyid == EVP_PKEY_KEYMGMT)
         pkeyid = lu->sig;
 
     /* Should never happen */
-    if (pkeyid == -1)
+    if (pkeyid == -1) {
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
         return -1;
+    }
 
     /*
      * Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
      * is consistent with signature: RSA keys can be used for RSA-PSS
      */
-    if (lu == NULL
-        || (SSL_CONNECTION_IS_TLS13(s)
+    if ((SSL_CONNECTION_IS_TLS13(s)
             && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
         || (pkeyid != lu->sig
         && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
@@ -3141,7 +3299,7 @@ static int tls12_sigalg_allowed(const SSL_CONNECTION *s, int op,
     unsigned char sigalgstr[2];
     int secbits;
 
-    if (lu == NULL || !lu->enabled)
+    if (lu == NULL || !lu->available)
         return 0;
     /* DSA is not allowed in TLS 1.3 */
     if (SSL_CONNECTION_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
@@ -3224,7 +3382,8 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL_CONNECTION *s, int op)
      */
     sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
     for (i = 0; i < sigalgslen; i++, sigalgs++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *sigalgs);
+        const SIGALG_LOOKUP *lu =
+            tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), *sigalgs);
         const SSL_CERT_LOOKUP *clu;
 
         if (lu == NULL)
@@ -3250,10 +3409,20 @@ int tls12_copy_sigalgs(SSL_CONNECTION *s, WPACKET *pkt,
     int rv = 0;
 
     for (i = 0; i < psiglen; i++, psig++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *psig);
+        const SIGALG_LOOKUP *lu =
+            tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), *psig);
+        int minversion, maxversion;
 
-        if (lu == NULL
-                || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
+        if (lu == NULL)
+            continue;
+        minversion = SSL_CONNECTION_IS_DTLS(s) ? lu->mindtls : lu->mintls;
+        maxversion = SSL_CONNECTION_IS_DTLS(s) ? lu->maxdtls : lu->maxtls;
+        if (minversion == -1 || maxversion == -1 || !lu->available
+            || (minversion != 0 && s->max_proto_version != 0
+                && ssl_version_cmp(s, minversion, s->max_proto_version) > 0)
+            || (maxversion != 0 && s->min_proto_version != 0
+                && ssl_version_cmp(s, maxversion, s->min_proto_version) < 0)
+            || !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
             continue;
         if (!WPACKET_put_bytes_u16(pkt, *psig))
             return 0;
@@ -3281,7 +3450,8 @@ static size_t tls12_shared_sigalgs(SSL_CONNECTION *s,
     const uint16_t *ptmp, *atmp;
     size_t i, j, nmatch = 0;
     for (i = 0, ptmp = pref; i < preflen; i++, ptmp++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *ptmp);
+        const SIGALG_LOOKUP *lu =
+            tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), *ptmp);
 
         /* Skip disabled hashes or signature algorithms */
         if (lu == NULL
@@ -3448,7 +3618,7 @@ int SSL_get_sigalgs(SSL *s, int idx,
             *rhash = (unsigned char)((*psig >> 8) & 0xff);
         if (rsig != NULL)
             *rsig = (unsigned char)(*psig & 0xff);
-        lu = tls1_lookup_sigalg(sc, *psig);
+        lu = tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(sc), *psig);
         if (psign != NULL)
             *psign = lu != NULL ? lu->sig : NID_undef;
         if (phash != NULL)
@@ -3553,32 +3723,31 @@ static int sig_cb(const char *elem, int len, void *arg)
      */
     if (p == NULL) {
         if (sarg->ctx != NULL) {
-            /* Check if a provider supports the sigalg */
-            for (i = 0; i < sarg->ctx->sigalg_list_len; i++) {
-                iana = sarg->ctx->sigalg_list[i].name;
-                alias = sarg->ctx->sigalg_list[i].sigalg_name;
+            for (i = 0; i < sarg->ctx->sigalg_lookup_cache_len; i++) {
+                iana = sarg->ctx->sigalg_lookup_cache[i].name;
+                alias = sarg->ctx->sigalg_lookup_cache[i].name12;
                 if ((alias != NULL && OPENSSL_strcasecmp(etmp, alias) == 0)
                     || OPENSSL_strcasecmp(etmp, iana) == 0) {
+                    /* Ignore known, but unavailable sigalgs. */
+                    if (!sarg->ctx->sigalg_lookup_cache[i].available)
+                        return 1;
                     sarg->sigalgs[sarg->sigalgcnt++] =
-                        sarg->ctx->sigalg_list[i].code_point;
-                    break;
+                        sarg->ctx->sigalg_lookup_cache[i].sigalg;
+                    goto found;
                 }
             }
-        }
-        /* Check the built-in sigalgs */
-        if (sarg->ctx == NULL || i == sarg->ctx->sigalg_list_len) {
+        } else {
+            /* Syntax checks use the built-in sigalgs */
             for (i = 0, s = sigalg_lookup_tbl;
                  i < OSSL_NELEM(sigalg_lookup_tbl); i++, s++) {
-                if (s->name != NULL
-                    && OPENSSL_strcasecmp(etmp, s->name) == 0) {
+                iana = s->name;
+                alias = s->name12;
+                if ((alias != NULL && OPENSSL_strcasecmp(etmp, alias) == 0)
+                    || OPENSSL_strcasecmp(etmp, iana) == 0) {
                     sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
-                    break;
+                    goto found;
                 }
             }
-            if (i == OSSL_NELEM(sigalg_lookup_tbl)) {
-                /* Ignore unknown algorithms if ignore_unknown */
-                return ignore_unknown;
-            }
         }
     } else {
         *p = 0;
@@ -3587,23 +3756,33 @@ static int sig_cb(const char *elem, int len, void *arg)
             return 0;
         get_sigorhash(&sig_alg, &hash_alg, etmp);
         get_sigorhash(&sig_alg, &hash_alg, p);
-        if (sig_alg == NID_undef || hash_alg == NID_undef) {
-            /* Ignore unknown algorithms if ignore_unknown */
-            return ignore_unknown;
-        }
-        for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
-             i++, s++) {
-            if (s->hash == hash_alg && s->sig == sig_alg) {
-                sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
-                break;
+        if (sig_alg != NID_undef && hash_alg != NID_undef) {
+            if (sarg->ctx != NULL) {
+                for (i = 0; i < sarg->ctx->sigalg_lookup_cache_len; i++) {
+                    s = &sarg->ctx->sigalg_lookup_cache[i];
+                    if (s->hash == hash_alg && s->sig == sig_alg) {
+                        /* Ignore known, but unavailable sigalgs. */
+                        if (!sarg->ctx->sigalg_lookup_cache[i].available)
+                            return 1;
+                        sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
+                        goto found;
+                    }
+                }
+            } else {
+                for (i = 0; i < OSSL_NELEM(sigalg_lookup_tbl); i++) {
+                    s = &sigalg_lookup_tbl[i];
+                    if (s->hash == hash_alg && s->sig == sig_alg) {
+                        sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
+                        goto found;
+                    }
+                }
             }
         }
-        if (i == OSSL_NELEM(sigalg_lookup_tbl)) {
-            /* Ignore unknown algorithms if ignore_unknown */
-            return ignore_unknown;
-        }
     }
+    /* Ignore unknown algorithms if ignore_unknown */
+    return ignore_unknown;
 
+ found:
     /* Ignore duplicates */
     for (i = 0; i < sarg->sigalgcnt - 1; i++) {
         if (sarg->sigalgs[i] == sarg->sigalgs[sarg->sigalgcnt - 1]) {
@@ -3729,7 +3908,8 @@ static int tls1_check_sig_alg(SSL_CONNECTION *s, X509 *x, int default_nid)
     }
     for (i = 0; i < sigalgslen; i++) {
         sigalg = use_pc_sigalgs
-                 ? tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i])
+                 ? tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s),
+                                      s->s3.tmp.peer_cert_sigalgs[i])
                  : s->shared_sigalgs[i];
         if (sigalg != NULL && sig_nid == sigalg->sigandhash)
             return 1;
@@ -3893,7 +4073,8 @@ int tls1_check_chain(SSL_CONNECTION *s, X509 *x, EVP_PKEY *pk,
             size_t j;
             const uint16_t *p = c->conf_sigalgs;
             for (j = 0; j < c->conf_sigalgslen; j++, p++) {
-                const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *p);
+                const SIGALG_LOOKUP *lu =
+                    tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s), *p);
 
                 if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
                     break;
@@ -4270,7 +4451,8 @@ static int check_cert_usable(SSL_CONNECTION *s, const SIGALG_LOOKUP *sig,
         if (!X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
             return 0;
         for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
-            lu = tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i]);
+            lu = tls1_lookup_sigalg(SSL_CONNECTION_GET_CTX(s),
+                                    s->s3.tmp.peer_cert_sigalgs[i]);
             if (lu == NULL)
                 continue;
 
@@ -4347,14 +4529,28 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL_CONNECTION *s, X509 *x,
 
     /* Look for a shared sigalgs matching possible certificates */
     for (i = 0; i < s->shared_sigalgslen; i++) {
-        lu = s->shared_sigalgs[i];
+        int dtls, minversion, maxversion;
 
         /* Skip SHA1, SHA224, DSA and RSA if not PSS */
+        lu = s->shared_sigalgs[i];
         if (lu->hash == NID_sha1
             || lu->hash == NID_sha224
             || lu->sig == EVP_PKEY_DSA
             || lu->sig == EVP_PKEY_RSA)
             continue;
+
+        /*
+         * By this point the protocol version should already be chosen.  Check
+         * the sigalg version bounds.
+         */
+        dtls = SSL_CONNECTION_IS_DTLS(s);
+        minversion = dtls ? lu->mindtls : lu->mintls;
+        maxversion = dtls ? lu->maxdtls : lu->maxtls;
+        if (minversion != 0 && ssl_version_cmp(s, minversion, s->version) > 0)
+            continue;
+        if (maxversion != 0 && ssl_version_cmp(s, maxversion, s->version) < 0)
+            continue;
+
         /* Check that we have a cert, and signature_algorithms_cert */
         if (!tls1_lookup_md(sctx, lu, NULL))
             continue;
@@ -4435,7 +4631,19 @@ int tls_choose_sigalg(SSL_CONNECTION *s, int fatalerrs)
                  * cert type
                  */
                 for (i = 0; i < s->shared_sigalgslen; i++) {
+                    int dtls, minversion, maxversion;
+
+                    /* Check the sigalg version bounds */
                     lu = s->shared_sigalgs[i];
+                    dtls = SSL_CONNECTION_IS_DTLS(s);
+                    minversion = dtls ? lu->mindtls : lu->mintls;
+                    maxversion = dtls ? lu->maxdtls : lu->maxtls;
+                    if (minversion != 0
+                        && ssl_version_cmp(s, minversion, s->version) > 0)
+                        continue;
+                    if (maxversion != 0
+                        && ssl_version_cmp(s, maxversion, s->version) < 0)
+                        continue;
 
                     if (s->server) {
                         if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
index d56eb5052a5ed45387c0bc8a97477126f962b46a..fabea52ef8b188c430b2835026c78a7cc3e2bf68 100644 (file)
@@ -2,8 +2,8 @@ Sent TLS Record
 Header:
   Version = TLS 1.0 (0x301)
   Content Type = Handshake (22)
-  Length = 1485
-    ClientHello, Length=1481
+  Length = ?
+    ClientHello, Length=?
       client_version=0x303 (TLS 1.2)
       Random:
         gmt_unix_time=0x?
@@ -13,7 +13,7 @@ Header:
         {0x13, 0x01} TLS_AES_128_GCM_SHA256
       compression_methods (len=1)
         No Compression (0x00)
-      extensions, length = 1438
+      extensions, length = ?
         extension_type=UNKNOWN(57), length=49
           0000 - 0c 00 0f 00 01 04 80 00-75 30 03 02 44 b0 0e   ........u0..D..
           000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06   ...............
@@ -37,27 +37,24 @@ Header:
           ossltest
         extension_type=encrypt_then_mac(22), length=0
         extension_type=extended_master_secret(23), length=0
-        extension_type=signature_algorithms(13), length=42
+        extension_type=signature_algorithms(13), length=?
+          mldsa65 (0x0905)
+          mldsa87 (0x0906)
+          mldsa44 (0x0904)
           ecdsa_secp256r1_sha256 (0x0403)
           ecdsa_secp384r1_sha384 (0x0503)
           ecdsa_secp521r1_sha512 (0x0603)
           ed25519 (0x0807)
           ed448 (0x0808)
-          ecdsa_brainpoolP256r1_sha256 (0x081a)
-          ecdsa_brainpoolP384r1_sha384 (0x081b)
-          ecdsa_brainpoolP512r1_sha512 (0x081c)
+          ecdsa_brainpoolP256r1tls13_sha256 (0x081a)
+          ecdsa_brainpoolP384r1tls13_sha384 (0x081b)
+          ecdsa_brainpoolP512r1tls13_sha512 (0x081c)
           rsa_pss_pss_sha256 (0x0809)
           rsa_pss_pss_sha384 (0x080a)
           rsa_pss_pss_sha512 (0x080b)
           rsa_pss_rsae_sha256 (0x0804)
           rsa_pss_rsae_sha384 (0x0805)
           rsa_pss_rsae_sha512 (0x0806)
-          rsa_pkcs1_sha256 (0x0401)
-          rsa_pkcs1_sha384 (0x0501)
-          rsa_pkcs1_sha512 (0x0601)
-          mldsa44 (0x0904)
-          mldsa65 (0x0905)
-          mldsa87 (0x0906)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
@@ -83,7 +80,7 @@ Sent Packet
   Packet Number: 0x00000000
 Sent Frame: Crypto
     Offset: 1158
-    Len: 327
+    Len: ?
 Sent Frame: Padding
 Sent Packet
   Packet Type: Initial
@@ -146,7 +143,7 @@ Received Frame: Ack  (without ECN)
 Received Frame: Padding
 Sent Frame: Crypto
     Offset: 1158
-    Len: 327
+    Len: ?
 Sent Frame: Padding
 Sent Packet
   Packet Type: Initial
index def4695a364899512259165f346e2cc2a8def31d..338c628b98cb534b6f5574d5fd619072079aee1f 100644 (file)
@@ -2,8 +2,8 @@ Sent TLS Record
 Header:
   Version = TLS 1.0 (0x301)
   Content Type = Handshake (22)
-  Length = 1478
-    ClientHello, Length=1474
+  Length = ?
+    ClientHello, Length=?
       client_version=0x303 (TLS 1.2)
       Random:
         gmt_unix_time=0x?
@@ -13,7 +13,7 @@ Header:
         {0x13, 0x01} TLS_AES_128_GCM_SHA256
       compression_methods (len=1)
         No Compression (0x00)
-      extensions, length = 1431
+      extensions, length = ?
         extension_type=UNKNOWN(57), length=49
           0000 - 0c 00 0f 00 01 04 80 00-75 30 03 02 44 b0 0e   ........u0..D..
           000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06   ...............
@@ -37,27 +37,24 @@ Header:
           ossltest
         extension_type=encrypt_then_mac(22), length=0
         extension_type=extended_master_secret(23), length=0
-        extension_type=signature_algorithms(13), length=42
+        extension_type=signature_algorithms(13), length=?
+          mldsa65 (0x0905)
+          mldsa87 (0x0906)
+          mldsa44 (0x0904)
           ecdsa_secp256r1_sha256 (0x0403)
           ecdsa_secp384r1_sha384 (0x0503)
           ecdsa_secp521r1_sha512 (0x0603)
           ed25519 (0x0807)
           ed448 (0x0808)
-          ecdsa_brainpoolP256r1_sha256 (0x081a)
-          ecdsa_brainpoolP384r1_sha384 (0x081b)
-          ecdsa_brainpoolP512r1_sha512 (0x081c)
+          ecdsa_brainpoolP256r1tls13_sha256 (0x081a)
+          ecdsa_brainpoolP384r1tls13_sha384 (0x081b)
+          ecdsa_brainpoolP512r1tls13_sha512 (0x081c)
           rsa_pss_pss_sha256 (0x0809)
           rsa_pss_pss_sha384 (0x080a)
           rsa_pss_pss_sha512 (0x080b)
           rsa_pss_rsae_sha256 (0x0804)
           rsa_pss_rsae_sha384 (0x0805)
           rsa_pss_rsae_sha512 (0x0806)
-          rsa_pkcs1_sha256 (0x0401)
-          rsa_pkcs1_sha384 (0x0501)
-          rsa_pkcs1_sha512 (0x0601)
-          mldsa44 (0x0904)
-          mldsa65 (0x0905)
-          mldsa87 (0x0906)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
@@ -81,7 +78,7 @@ Sent Packet
   Packet Number: 0x00000000
 Sent Frame: Crypto
     Offset: 1158
-    Len: 320
+    Len: ?
 Sent Frame: Padding
 Sent Packet
   Packet Type: Initial
@@ -144,7 +141,7 @@ Received Frame: Ack  (without ECN)
 Received Frame: Padding
 Sent Frame: Crypto
     Offset: 1158
-    Len: 320
+    Len: ?
 Sent Frame: Padding
 Sent Packet
   Packet Type: Initial
index 09acf8c3841c38c8ee3b50c1ed1e7051980a081e..38e46e4bb929af6958a7666e6d45d36f03d5c802 100644 (file)
        {"name" : "test-tls13-certificate-verify.py",
         "arguments" : ["-k", "tests/clientX509Key.pem",
                        "-c", "tests/clientX509Cert.pem",
-                       "-s", "ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 ecdsa_sha224 rsa_pkcs1_sha224 9+4 9+5 9+6",
+                       "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 ecdsa_sha224 rsa_pkcs1_sha224",
                        "-p", "@PORT@"]},
        {"name" : "test-tls13-ecdsa-in-certificate-verify.py",
           "arguments" : ["-k", "tests/serverECKey.pem",
                          "-c", "tests/serverECCert.pem",
-                         "-s", "ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 ecdsa_sha224 rsa_pkcs1_sha224 9+4 9+5 9+6",
+                         "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 ecdsa_sha224 rsa_pkcs1_sha224",
                          "-p", "@PORT@"]}
      ]
     },
index 2b3abb19d78207436a6dd5bf3a0d27425cf49c02..0228c04cc303f2fe1ab4dc565ad76aee6e039387 100644 (file)
@@ -573,6 +573,8 @@ my %params = (
     'CAPABILITY_TLS_SIGALG_SECURITY_BITS' =>     "tls-sigalg-sec-bits",
     'CAPABILITY_TLS_SIGALG_MIN_TLS' =>           "tls-min-tls",
     'CAPABILITY_TLS_SIGALG_MAX_TLS' =>           "tls-max-tls",
+    'CAPABILITY_TLS_SIGALG_MIN_DTLS' =>          "tls-min-dtls",
+    'CAPABILITY_TLS_SIGALG_MAX_DTLS' =>          "tls-max-dtls",
 
 # storemgmt parameters