[openssl] master update

Matt Caswell matt at openssl.org
Fri Jun 5 09:42:01 UTC 2020


The branch master has been updated
       via  0d52ede71685e4176999cc5e52000dcb540747fc (commit)
       via  b38425393c76ff31560d6b0bdb0b097e7d93ffc4 (commit)
       via  3cd69b7458f1dfa274d4d8fe1a46a35d91e9008c (commit)
       via  d01d375264e73f49a416409e2f8febe88ad39c8a (commit)
       via  5f603a280ca71b7136861b9bc408f37fd1c4e0d7 (commit)
       via  263ff2c9d4c88f19133d21d9956d71edd7401d54 (commit)
      from  eca471391378139f76a7d1229b6a5a1dcc4b5603 (commit)


- Log -----------------------------------------------------------------
commit 0d52ede71685e4176999cc5e52000dcb540747fc
Author: Matt Caswell <matt at openssl.org>
Date:   Wed May 13 14:45:36 2020 +0100

    Fix error path in int create_ssl_ctx_pair()
    
    If we hit the error path and create_ssl_ctx_pair has been passed a
    pre-created SSL_CTX then we could end up with a double free.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

commit b38425393c76ff31560d6b0bdb0b097e7d93ffc4
Author: Matt Caswell <matt at openssl.org>
Date:   Fri May 8 16:43:14 2020 +0100

    Implement a test for sigalgs not being present
    
    If sigalgs are not present we should not offer or accept them. We should
    test that we handle this correctly.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

commit 3cd69b7458f1dfa274d4d8fe1a46a35d91e9008c
Author: Matt Caswell <matt at openssl.org>
Date:   Mon May 4 16:26:07 2020 +0100

    Implement a Filtering Provider
    
    The filtering provider can be used to place a filter in front of the
    default provider. Initially to filter out certain algorithms from being
    available for test purposes.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

commit d01d375264e73f49a416409e2f8febe88ad39c8a
Author: Matt Caswell <matt at openssl.org>
Date:   Fri May 8 16:44:02 2020 +0100

    Implement OSSL_PROVIDER_get0_provider_ctx()
    
    Implement a function which enables us to get hold of the provider ctx
    for a loaded provider.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

commit 5f603a280ca71b7136861b9bc408f37fd1c4e0d7
Author: Matt Caswell <matt at openssl.org>
Date:   Mon May 4 15:28:15 2020 +0100

    Enable applications to directly call a provider's query operation
    
    This is useful to get hold of the low-level dispatch tables. This could
    be used to create a new provider based on an existing one.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

commit 263ff2c9d4c88f19133d21d9956d71edd7401d54
Author: Matt Caswell <matt at openssl.org>
Date:   Fri May 1 17:41:25 2020 +0100

    Check that Signature Algorithms are available before using them
    
    We should confirm that Signature Algorithms are actually available
    through the loaded providers before we offer or select them.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11834)

-----------------------------------------------------------------------

Summary of changes:
 crypto/provider.c           |  13 +++
 crypto/provider_core.c      |   8 ++
 doc/man3/OSSL_PROVIDER.pod  |  23 +++++
 include/internal/provider.h |   1 +
 include/openssl/provider.h  |   5 ++
 ssl/ssl_lib.c               |   6 ++
 ssl/ssl_local.h             |   6 ++
 ssl/t1_lib.c                | 149 ++++++++++++++++++++++-----------
 test/build.info             |   2 +-
 test/filterprov.c           | 199 ++++++++++++++++++++++++++++++++++++++++++++
 test/sslapitest.c           | 160 +++++++++++++++++++++++++++++++++--
 test/ssltestlib.c           |   6 +-
 util/libcrypto.num          |   2 +
 13 files changed, 525 insertions(+), 55 deletions(-)
 create mode 100644 test/filterprov.c

diff --git a/crypto/provider.c b/crypto/provider.c
index 13438cefe3..02002a5f95 100644
--- a/crypto/provider.c
+++ b/crypto/provider.c
@@ -57,6 +57,19 @@ int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
     return ossl_provider_get_params(prov, params);
 }
 
+
+const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+                                                    int operation_id,
+                                                    int *no_cache)
+{
+    return ossl_provider_query_operation(prov, operation_id, no_cache);
+}
+
+void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
+{
+    return ossl_provider_prov_ctx(prov);
+}
+
 int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *libctx, const char *name,
                               OSSL_provider_init_fn *init_fn)
 {
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 8b868fdb6b..f7af51a297 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -787,6 +787,14 @@ const char *ossl_provider_module_path(const OSSL_PROVIDER *prov)
 #endif
 }
 
+void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov)
+{
+    if (prov != NULL)
+        return prov->provctx;
+
+    return NULL;
+}
+
 OPENSSL_CTX *ossl_provider_library_context(const OSSL_PROVIDER *prov)
 {
     /* TODO(3.0) just: return prov->libctx; */
diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod
index 93d6e1421c..d6f0af53c9 100644
--- a/doc/man3/OSSL_PROVIDER.pod
+++ b/doc/man3/OSSL_PROVIDER.pod
@@ -6,6 +6,7 @@ OSSL_PROVIDER_set_default_search_path,
 OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_unload,
 OSSL_PROVIDER_available, OSSL_PROVIDER_do_all,
 OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params,
+OSSL_PROVIDER_query_operation, OSSL_PROVIDER_get0_provider_ctx,
 OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines
 
 =head1 SYNOPSIS
@@ -27,6 +28,11 @@ OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines
  const OSSL_PARAM *OSSL_PROVIDER_gettable_params(OSSL_PROVIDER *prov);
  int OSSL_PROVIDER_get_params(OSSL_PROVIDER *prov, OSSL_PARAM params[]);
 
+ const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+                                                     int operation_id,
+                                                     int *no_cache);
+ void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
+
  int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *libctx, const char *name,
                                ossl_provider_init_fn *init_fn);
 
@@ -82,6 +88,20 @@ The caller must prepare the B<OSSL_PARAM> array before calling this
 function, and the variables acting as buffers for this parameter array
 should be filled with data when it returns successfully.
 
+OSSL_PROVIDER_query_operation() calls the provider's I<query_operation>
+function (see L<provider(7)>), if the provider has one. It returns an
+array of I<OSSL_ALGORITHM> for the given I<operation_id> terminated by an all
+NULL OSSL_ALGORITHM entry. This is considered a low-level function that most
+applications should not need to call.
+
+OSSL_PROVIDER_get0_provider_ctx() returns the provider context for the given
+provider. The provider context is an opaque handle set by the provider itself
+and is passed back to the provider by libcrypto in various function calls.
+
+If it is permissible to cache references to this array then I<*no_store> is set
+to 0 or 1 otherwise. If the array is not cacheable then it is assumed to
+have a short lifetime.
+
 OSSL_PROVIDER_name() returns the name of the given provider.
 
 =head1 RETURN VALUES
@@ -101,6 +121,9 @@ of constant B<OSSL_PARAM>, or NULL if none is provided.
 
 OSSL_PROVIDER_get_params() returns 1 on success, or 0 on error.
 
+OSSL_PROVIDER_query_operation() returns an array of OSSL_ALGORITHM or NULL on
+error.
+
 =head1 EXAMPLES
 
 This demonstrates how to load the provider module "foo" and ask for
diff --git a/include/internal/provider.h b/include/internal/provider.h
index 135b660f49..d7c0926a0b 100644
--- a/include/internal/provider.h
+++ b/include/internal/provider.h
@@ -64,6 +64,7 @@ const char *ossl_provider_name(const OSSL_PROVIDER *prov);
 const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov);
 const char *ossl_provider_module_name(const OSSL_PROVIDER *prov);
 const char *ossl_provider_module_path(const OSSL_PROVIDER *prov);
+void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov);
 OPENSSL_CTX *ossl_provider_library_context(const OSSL_PROVIDER *prov);
 
 /* Thin wrappers around calls to the provider */
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
index 6ce68b16e7..e9a1408675 100644
--- a/include/openssl/provider.h
+++ b/include/openssl/provider.h
@@ -30,6 +30,11 @@ int OSSL_PROVIDER_do_all(OPENSSL_CTX *ctx,
 const OSSL_PARAM *OSSL_PROVIDER_gettable_params(const OSSL_PROVIDER *prov);
 int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
 
+const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
+                                                    int operation_id,
+                                                    int *no_cache);
+void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
+
 /* Add a built in providers */
 int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *, const char *name,
                               OSSL_provider_init_fn *init_fn);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index cb02129d9d..c2c2388716 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3166,6 +3166,10 @@ SSL_CTX *SSL_CTX_new_with_libctx(OPENSSL_CTX *libctx, const char *propq,
     /* initialize cipher/digest methods table */
     if (!ssl_load_ciphers(ret))
         goto err2;
+    /* initialise sig algs */
+    if (!ssl_setup_sig_algs(ret))
+        goto err2;
+
 
     if (!SSL_CTX_set_ciphersuites(ret, OSSL_default_ciphersuites()))
         goto err;
@@ -3386,6 +3390,8 @@ void SSL_CTX_free(SSL_CTX *a)
     for (i = 0; i < SSL_MD_NUM_IDX; i++)
         ssl_evp_md_free(a->ssl_digest_methods[i]);
 
+    OPENSSL_free(a->sigalg_lookup_cache);
+
     CRYPTO_THREAD_lock_free(a->lock);
 
     OPENSSL_free(a->propq);
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 5e2379c093..d2e8e23e23 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -1157,6 +1157,9 @@ struct ssl_ctx_st {
     const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
     const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX];
     size_t ssl_mac_secret_size[SSL_MD_NUM_IDX];
+
+    /* Cache of all sigalgs we know and whether they are available or not */
+    struct sigalg_lookup_st *sigalg_lookup_cache;
 };
 
 typedef struct cert_pkey_st CERT_PKEY;
@@ -1776,6 +1779,8 @@ typedef struct sigalg_lookup_st {
     int sigandhash;
     /* Required public key curve (ECDSA only) */
     int curve;
+    /* Whether this signature algorithm is actually available for use */
+    int enabled;
 } SIGALG_LOOKUP;
 
 typedef struct tls_group_info_st {
@@ -2432,6 +2437,7 @@ __owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
 __owur int ssl_x509err2alert(int type);
 void ssl_sort_cipher_list(void);
 int ssl_load_ciphers(SSL_CTX *ctx);
+__owur int ssl_setup_sig_algs(SSL_CTX *ctx);
 __owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field,
                                  size_t len, DOWNGRADE dgrd);
 __owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 5afe53acfc..a59d992e47 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -793,97 +793,97 @@ static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {
 #ifndef OPENSSL_NO_EC
     {"ecdsa_secp256r1_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},
+     NID_ecdsa_with_SHA256, NID_X9_62_prime256v1, 1},
     {"ecdsa_secp384r1_sha384", TLSEXT_SIGALG_ecdsa_secp384r1_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA384, NID_secp384r1},
+     NID_ecdsa_with_SHA384, NID_secp384r1, 1},
     {"ecdsa_secp521r1_sha512", TLSEXT_SIGALG_ecdsa_secp521r1_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA512, NID_secp521r1},
+     NID_ecdsa_with_SHA512, NID_secp521r1, 1},
     {"ed25519", TLSEXT_SIGALG_ed25519,
      NID_undef, -1, EVP_PKEY_ED25519, SSL_PKEY_ED25519,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {"ed448", TLSEXT_SIGALG_ed448,
      NID_undef, -1, EVP_PKEY_ED448, SSL_PKEY_ED448,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_ecdsa_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA224, NID_undef},
+     NID_ecdsa_with_SHA224, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_ecdsa_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_EC, SSL_PKEY_ECC,
-     NID_ecdsa_with_SHA1, NID_undef},
+     NID_ecdsa_with_SHA1, NID_undef, 1},
 #endif
     {"rsa_pss_rsae_sha256", TLSEXT_SIGALG_rsa_pss_rsae_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {"rsa_pss_rsae_sha384", TLSEXT_SIGALG_rsa_pss_rsae_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {"rsa_pss_rsae_sha512", TLSEXT_SIGALG_rsa_pss_rsae_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA_PSS, SSL_PKEY_RSA,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {"rsa_pss_pss_sha256", 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},
+     NID_undef, NID_undef, 1},
     {"rsa_pss_pss_sha384", 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},
+     NID_undef, NID_undef, 1},
     {"rsa_pss_pss_sha512", 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},
+     NID_undef, NID_undef, 1},
     {"rsa_pkcs1_sha256", TLSEXT_SIGALG_rsa_pkcs1_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha256WithRSAEncryption, NID_undef},
+     NID_sha256WithRSAEncryption, NID_undef, 1},
     {"rsa_pkcs1_sha384", TLSEXT_SIGALG_rsa_pkcs1_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha384WithRSAEncryption, NID_undef},
+     NID_sha384WithRSAEncryption, NID_undef, 1},
     {"rsa_pkcs1_sha512", TLSEXT_SIGALG_rsa_pkcs1_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha512WithRSAEncryption, NID_undef},
+     NID_sha512WithRSAEncryption, NID_undef, 1},
     {"rsa_pkcs1_sha224", TLSEXT_SIGALG_rsa_pkcs1_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha224WithRSAEncryption, NID_undef},
+     NID_sha224WithRSAEncryption, NID_undef, 1},
     {"rsa_pkcs1_sha1", TLSEXT_SIGALG_rsa_pkcs1_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_sha1WithRSAEncryption, NID_undef},
+     NID_sha1WithRSAEncryption, NID_undef, 1},
 #ifndef OPENSSL_NO_DSA
     {NULL, TLSEXT_SIGALG_dsa_sha256,
      NID_sha256, SSL_MD_SHA256_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_dsa_with_SHA256, NID_undef},
+     NID_dsa_with_SHA256, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_dsa_sha384,
      NID_sha384, SSL_MD_SHA384_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_dsa_sha512,
      NID_sha512, SSL_MD_SHA512_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_dsa_sha224,
      NID_sha224, SSL_MD_SHA224_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_undef, NID_undef},
+     NID_undef, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_dsa_sha1,
      NID_sha1, SSL_MD_SHA1_IDX, EVP_PKEY_DSA, SSL_PKEY_DSA_SIGN,
-     NID_dsaWithSHA1, NID_undef},
+     NID_dsaWithSHA1, NID_undef, 1},
 #endif
 #ifndef OPENSSL_NO_GOST
     {NULL, 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},
+     NID_undef, NID_undef, 1},
     {NULL, 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},
+     NID_undef, NID_undef, 1},
     {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},
+     NID_undef, NID_undef, 1},
     {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},
+     NID_undef, NID_undef, 1},
     {NULL, TLSEXT_SIGALG_gostr34102001_gostr3411,
      NID_id_GostR3411_94, SSL_MD_GOST94_IDX,
      NID_id_GostR3410_2001, SSL_PKEY_GOST01,
-     NID_undef, NID_undef}
+     NID_undef, NID_undef, 1}
 #endif
 };
 /* Legacy sigalgs for TLS < 1.2 RSA TLS signatures */
@@ -891,7 +891,7 @@ static const SIGALG_LOOKUP legacy_rsa_sigalg = {
     "rsa_pkcs1_md5_sha1", 0,
      NID_md5_sha1, SSL_MD_MD5_SHA1_IDX,
      EVP_PKEY_RSA, SSL_PKEY_RSA,
-     NID_undef, NID_undef
+     NID_undef, NID_undef, 1
 };
 
 /*
@@ -910,16 +910,72 @@ static const uint16_t tls_default_sigalg[] = {
     0, /* SSL_PKEY_ED448 */
 };
 
+int ssl_setup_sig_algs(SSL_CTX *ctx)
+{
+    size_t i;
+    const SIGALG_LOOKUP *lu;
+    SIGALG_LOOKUP *cache
+        = OPENSSL_malloc(sizeof(*lu) * OSSL_NELEM(sigalg_lookup_tbl));
+    EVP_PKEY *tmpkey = EVP_PKEY_new();
+    int ret = 0;
+
+    if (cache == NULL || tmpkey == NULL)
+        goto err;
+
+    ERR_set_mark();
+    for (i = 0, lu = sigalg_lookup_tbl;
+         i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) {
+        EVP_PKEY_CTX *pctx;
+
+        cache[i] = *lu;
+
+        /*
+         * Check hash is available.
+         * TODO(3.0): This test is not perfect. A provider could have support
+         * for a signature scheme, but not a particular hash. However the hash
+         * could be available from some other loaded provider. In that case it
+         * could be that the signature is available, and the hash is available
+         * independently - but not as a combination. We ignore this for now.
+         */
+        if (lu->hash != NID_undef
+                && ctx->ssl_digest_methods[lu->hash_idx] == NULL) {
+            cache[i].enabled = 0;
+            continue;
+        }
+
+        if (!EVP_PKEY_set_type(tmpkey, lu->sig)) {
+            cache[i].enabled = 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;
+        EVP_PKEY_CTX_free(pctx);
+    }
+    ERR_pop_to_mark();
+    ctx->sigalg_lookup_cache = cache;
+    cache = NULL;
+
+    ret = 1;
+ err:
+    OPENSSL_free(cache);
+    EVP_PKEY_free(tmpkey);
+    return ret;
+}
+
 /* Lookup TLS signature algorithm */
-static const SIGALG_LOOKUP *tls1_lookup_sigalg(uint16_t sigalg)
+static const SIGALG_LOOKUP *tls1_lookup_sigalg(const SSL *s, uint16_t sigalg)
 {
     size_t i;
-    const SIGALG_LOOKUP *s;
+    const SIGALG_LOOKUP *lu;
 
-    for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
-         i++, s++) {
-        if (s->sigalg == sigalg)
-            return s;
+    for (i = 0, lu = s->ctx->sigalg_lookup_cache;
+         /* cache should have the same number of elements as sigalg_lookup_tbl */
+         i < OSSL_NELEM(sigalg_lookup_tbl);
+         lu++, i++) {
+        if (lu->sigalg == sigalg)
+            return lu;
     }
     return NULL;
 }
@@ -1023,7 +1079,7 @@ static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
     if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
         return NULL;
     if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);
+        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, tls_default_sigalg[idx]);
 
         if (!tls1_lookup_md(s->ctx, lu, NULL))
             return NULL;
@@ -1107,7 +1163,7 @@ int tls_check_sigalg_curve(const SSL *s, int curve)
     }
 
     for (i = 0; i < siglen; i++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);
+        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, sigs[i]);
 
         if (lu == NULL)
             continue;
@@ -1187,7 +1243,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
         if (pkeyid == EVP_PKEY_RSA)
             pkeyid = EVP_PKEY_RSA_PSS;
     }
-    lu = tls1_lookup_sigalg(sig);
+    lu = tls1_lookup_sigalg(s, sig);
     /*
      * 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
@@ -1761,8 +1817,7 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
     unsigned char sigalgstr[2];
     int secbits;
 
-    /* See if sigalgs is recognised and if hash is enabled */
-    if (!tls1_lookup_md(s->ctx, lu, NULL))
+    if (lu == NULL || !lu->enabled)
         return 0;
     /* DSA is not allowed in TLS 1.3 */
     if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
@@ -1841,7 +1896,7 @@ void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op)
      */
     sigalgslen = tls12_get_psigalgs(s, 1, &sigalgs);
     for (i = 0; i < sigalgslen; i++, sigalgs++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*sigalgs);
+        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *sigalgs);
         const SSL_CERT_LOOKUP *clu;
 
         if (lu == NULL)
@@ -1866,7 +1921,7 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
     int rv = 0;
 
     for (i = 0; i < psiglen; i++, psig++) {
-        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*psig);
+        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *psig);
 
         if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
             continue;
@@ -1895,7 +1950,7 @@ static size_t tls12_shared_sigalgs(SSL *s, const SIGALG_LOOKUP **shsig,
     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(*ptmp);
+        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *ptmp);
 
         /* Skip disabled hashes or signature algorithms */
         if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, lu))
@@ -2056,7 +2111,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(*psig);
+        lu = tls1_lookup_sigalg(s, *psig);
         if (psign != NULL)
             *psign = lu != NULL ? lu->sig : NID_undef;
         if (phash != NULL)
@@ -2294,7 +2349,7 @@ static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
     }
     for (i = 0; i < sigalgslen; i++) {
         sigalg = use_pc_sigalgs
-                 ? tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i])
+                 ? tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i])
                  : s->shared_sigalgs[i];
         if (sigalg != NULL && sig_nid == sigalg->sigandhash)
             return 1;
@@ -2442,7 +2497,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
             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(*p);
+                const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(s, *p);
 
                 if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
                     break;
@@ -2777,7 +2832,7 @@ static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
         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->s3.tmp.peer_cert_sigalgs[i]);
+            lu = tls1_lookup_sigalg(s, s->s3.tmp.peer_cert_sigalgs[i]);
             if (lu == NULL)
                 continue;
 
diff --git a/test/build.info b/test/build.info
index 3255a836de..868b8ebefa 100644
--- a/test/build.info
+++ b/test/build.info
@@ -290,7 +290,7 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[param_build_test]=../include ../apps/include
   DEPEND[param_build_test]=../libcrypto.a libtestutil.a
 
-  SOURCE[sslapitest]=sslapitest.c ssltestlib.c
+  SOURCE[sslapitest]=sslapitest.c ssltestlib.c filterprov.c
   INCLUDE[sslapitest]=../include ../apps/include ..
   DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a
 
diff --git a/test/filterprov.c b/test/filterprov.c
new file mode 100644
index 0000000000..9fe6690e50
--- /dev/null
+++ b/test/filterprov.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * A filtering provider for test purposes. We pass all calls through to the
+ * default provider except where we want other behaviour for a test.
+ */
+
+#include <string.h>
+#include <openssl/core.h>
+#include <openssl/core_numbers.h>
+#include <openssl/provider.h>
+#include <openssl/crypto.h>
+
+OSSL_provider_init_fn filter_provider_init;
+
+int filter_provider_set_filter(int operation, const char *name);
+
+#define MAX_FILTERS     10
+#define MAX_ALG_FILTERS 5
+
+struct filter_prov_globals_st {
+    OPENSSL_CTX *libctx;
+    OSSL_PROVIDER *deflt;
+    struct {
+        int operation;
+        OSSL_ALGORITHM alg[MAX_ALG_FILTERS + 1];
+    } dispatch[MAX_FILTERS];
+    int num_dispatch;
+};
+
+static struct filter_prov_globals_st ourglobals;
+
+static struct filter_prov_globals_st *get_globals(void)
+{
+    /*
+     * Ideally we'd like to store this in the OPENSSL_CTX so that we can have
+     * more than one instance of the filter provider at a time. But for now we
+     * just make it simple.
+     */
+    return &ourglobals;
+}
+
+static OSSL_provider_gettable_params_fn filter_gettable_params;
+static OSSL_provider_get_params_fn filter_get_params;
+static OSSL_provider_query_operation_fn filter_query;
+static OSSL_provider_teardown_fn filter_teardown;
+
+static const OSSL_PARAM *filter_gettable_params(void *provctx)
+{
+    struct filter_prov_globals_st *globs = get_globals();
+
+    return OSSL_PROVIDER_gettable_params(globs->deflt);
+}
+
+static int filter_get_params(void *provctx, OSSL_PARAM params[])
+{
+    struct filter_prov_globals_st *globs = get_globals();
+
+    return OSSL_PROVIDER_get_params(globs->deflt, params);
+}
+
+static const OSSL_ALGORITHM *filter_query(void *provctx,
+                                          int operation_id,
+                                          int *no_cache)
+{
+    struct filter_prov_globals_st *globs = get_globals();
+    int i;
+
+    for (i = 0; i < globs->num_dispatch; i++) {
+        if (globs->dispatch[i].operation == operation_id) {
+            *no_cache = 0;
+            return globs->dispatch[i].alg;
+        }
+    }
+
+    /* No filter set, so pass it down to the chained provider */
+    return OSSL_PROVIDER_query_operation(globs->deflt, operation_id, no_cache);
+}
+
+static void filter_teardown(void *provctx)
+{
+    struct filter_prov_globals_st *globs = get_globals();
+
+    OSSL_PROVIDER_unload(globs->deflt);
+    OPENSSL_CTX_free(globs->libctx);
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH filter_dispatch_table[] = {
+    { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))filter_gettable_params },
+    { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))filter_get_params },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))filter_query },
+    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))filter_teardown },
+    { 0, NULL }
+};
+
+int filter_provider_init(const OSSL_CORE_HANDLE *handle,
+                         const OSSL_DISPATCH *in,
+                         const OSSL_DISPATCH **out,
+                         void **provctx)
+{
+    memset(&ourglobals, 0, sizeof(ourglobals));
+    ourglobals.libctx = OPENSSL_CTX_new();
+    if (ourglobals.libctx == NULL)
+        goto err;
+
+    ourglobals.deflt = OSSL_PROVIDER_load(ourglobals.libctx, "default");
+    if (ourglobals.deflt == NULL)
+        goto err;
+
+    *provctx = OSSL_PROVIDER_get0_provider_ctx(ourglobals.deflt);
+    *out = filter_dispatch_table;
+    return 1;
+
+ err:
+    OSSL_PROVIDER_unload(ourglobals.deflt);
+    OPENSSL_CTX_free(ourglobals.libctx);
+    return 0;
+}
+
+/*
+ * Set a filter for the given operation id. The filter string is a colon
+ * separated list of algorithms that will be made available by this provider.
+ * Anything not in the filter will be suppressed. If a filter is not set for
+ * a given operation id then all algorithms are made available.
+ */
+int filter_provider_set_filter(int operation, const char *filterstr)
+{
+    int no_cache = 0;
+    int algnum = 0, last = 0, ret = 0;
+    struct filter_prov_globals_st *globs = get_globals();
+    size_t namelen;
+    char *filterstrtmp = OPENSSL_strdup(filterstr);
+    char *name, *sep;
+    const OSSL_ALGORITHM *provalgs = OSSL_PROVIDER_query_operation(globs->deflt,
+                                                                   operation,
+                                                                   &no_cache);
+    const OSSL_ALGORITHM *algs;
+
+    if (filterstrtmp == NULL)
+        goto err;
+
+    /* We don't support no_cache */
+    if (no_cache)
+        goto err;
+
+    /* Nothing to filter */
+    if (provalgs == NULL)
+        goto err;
+
+    if (globs->num_dispatch >= MAX_FILTERS)
+        goto err;
+
+    for (name = filterstrtmp; !last; name = sep + 1) {
+        sep = strstr(name, ":");
+        if (sep != NULL)
+            *sep = '\0';
+        else
+            last = 1;
+        namelen = strlen(name);
+
+        for (algs = provalgs; algs->algorithm_names != NULL; algs++) {
+            const char *found = strstr(algs->algorithm_names, name);
+
+            if (found == NULL)
+                continue;
+            if (found[namelen] != '\0' && found[namelen] != ':')
+                continue;
+            if (found != algs->algorithm_names && found[-1] != ':')
+                continue;
+
+            /* We found a match */
+            if (algnum >= MAX_ALG_FILTERS)
+                goto err;
+
+            globs->dispatch[globs->num_dispatch].alg[algnum++] = *algs;
+            break;
+        }
+        if (algs->algorithm_names == NULL) {
+            /* No match found */
+            goto err;
+        }
+    }
+
+    globs->dispatch[globs->num_dispatch].operation = operation;
+    globs->num_dispatch++;
+
+    ret = 1;
+ err:
+    OPENSSL_free(filterstrtmp);
+    return ret;
+}
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 423da560ae..8847ba38ce 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -28,6 +28,7 @@
 #include <openssl/aes.h>
 #include <openssl/rand.h>
 #include <openssl/core_names.h>
+#include <openssl/core_numbers.h>
 #include <openssl/provider.h>
 
 #include "ssltestlib.h"
@@ -37,6 +38,10 @@
 #include "internal/ktls.h"
 #include "../ssl/ssl_local.h"
 
+/* Defined in filterprov.c */
+OSSL_provider_init_fn filter_provider_init;
+int filter_provider_set_filter(int operation, const char *name);
+
 DEFINE_STACK_OF(OCSP_RESPID)
 DEFINE_STACK_OF(X509)
 DEFINE_STACK_OF(X509_NAME)
@@ -65,6 +70,8 @@ static SSL_SESSION *create_a_psk(SSL *ssl);
 static char *certsdir = NULL;
 static char *cert = NULL;
 static char *privkey = NULL;
+static char *cert2 = NULL;
+static char *privkey2 = NULL;
 static char *srpvfile = NULL;
 static char *tmpfilename = NULL;
 
@@ -7664,6 +7671,131 @@ static int test_servername(int tst)
     return testresult;
 }
 
+#ifndef OPENSSL_NO_EC
+/*
+ * Test that if signature algorithms are not available, then we do not offer or
+ * accept them.
+ * Test 0: Two RSA sig algs available: both RSA sig algs shared
+ * Test 1: The client only has SHA2-256: only SHA2-256 algorithms shared
+ * Test 2: The server only has SHA2-256: only SHA2-256 algorithms shared
+ * Test 3: An RSA and an ECDSA sig alg available: both sig algs shared
+ * Test 4: The client only has an ECDSA sig alg: only ECDSA algorithms shared
+ * Test 5: The server only has an ECDSA sig alg: only ECDSA algorithms shared
+ */
+static int test_sigalgs_available(int idx)
+{
+    SSL_CTX *cctx = NULL, *sctx = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    int testresult = 0;
+    OPENSSL_CTX *tmpctx = OPENSSL_CTX_new();
+    OPENSSL_CTX *clientctx = libctx, *serverctx = libctx;
+    OSSL_PROVIDER *filterprov = NULL;
+    int sig, hash;
+
+    if (!TEST_ptr(tmpctx))
+        goto end;
+
+    if (idx != 0 && idx != 3) {
+        if (!TEST_true(OSSL_PROVIDER_add_builtin(tmpctx, "filter",
+                                                 filter_provider_init)))
+            goto end;
+
+        filterprov = OSSL_PROVIDER_load(tmpctx, "filter");
+        if (!TEST_ptr(filterprov))
+            goto end;
+
+        if (idx < 3) {
+            /*
+             * Only enable SHA2-256 so rsa_pss_rsae_sha384 should not be offered
+             * or accepted for the peer that uses this libctx. Note that libssl
+             * *requires* SHA2-256 to be available so we cannot disable that. We
+             * also need SHA1 for our certificate.
+             */
+            if (!TEST_true(filter_provider_set_filter(OSSL_OP_DIGEST,
+                                                      "SHA2-256:SHA1")))
+                goto end;
+        } else {
+            if (!TEST_true(filter_provider_set_filter(OSSL_OP_SIGNATURE,
+                                                      "ECDSA"))
+                    || !TEST_true(filter_provider_set_filter(OSSL_OP_KEYMGMT,
+                                                             "EC:X25519:X448")))
+                goto end;
+        }
+
+        if (idx == 1 || idx == 4)
+            clientctx = tmpctx;
+        else
+            serverctx = tmpctx;
+    }
+
+    cctx = SSL_CTX_new_with_libctx(clientctx, NULL, TLS_client_method());
+    sctx = SSL_CTX_new_with_libctx(serverctx, NULL, TLS_server_method());
+
+    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+                                       TLS_client_method(),
+                                       TLS1_VERSION,
+                                       0,
+                                       &sctx, &cctx, cert, privkey)))
+        goto end;
+
+    if (idx < 3) {
+        if (!SSL_CTX_set1_sigalgs_list(cctx,
+                                       "rsa_pss_rsae_sha384"
+                                       ":rsa_pss_rsae_sha256")
+                || !SSL_CTX_set1_sigalgs_list(sctx,
+                                              "rsa_pss_rsae_sha384"
+                                              ":rsa_pss_rsae_sha256"))
+            goto end;
+    } else {
+        if (!SSL_CTX_set1_sigalgs_list(cctx, "rsa_pss_rsae_sha256:ECDSA+SHA256")
+                || !SSL_CTX_set1_sigalgs_list(sctx,
+                                              "rsa_pss_rsae_sha256:ECDSA+SHA256"))
+            goto end;
+    }
+
+    if (!TEST_int_eq(SSL_CTX_use_certificate_file(sctx, cert2,
+                                                  SSL_FILETYPE_PEM), 1)
+            || !TEST_int_eq(SSL_CTX_use_PrivateKey_file(sctx,
+                                                        privkey2,
+                                                        SSL_FILETYPE_PEM), 1)
+            || !TEST_int_eq(SSL_CTX_check_private_key(sctx), 1))
+        goto end;
+
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+                                             NULL, NULL)))
+        goto end;
+
+    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+        goto end;
+
+    /* For tests 0 and 3 we expect 2 shared sigalgs, otherwise exactly 1 */
+    if (!TEST_int_eq(SSL_get_shared_sigalgs(serverssl, 0, &sig, &hash, NULL,
+                                            NULL, NULL),
+                     (idx == 0 || idx == 3) ? 2 : 1))
+        goto end;
+
+    if (!TEST_int_eq(hash, idx == 0 ? NID_sha384 : NID_sha256))
+        goto end;
+
+    if (!TEST_int_eq(sig, (idx == 4 || idx == 5) ? EVP_PKEY_EC
+                                                 : NID_rsassaPss))
+        goto end;
+
+    testresult = 1;
+
+ end:
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+    OSSL_PROVIDER_unload(filterprov);
+    OPENSSL_CTX_free(tmpctx);
+
+    return testresult;
+}
+#endif /* OPENSSL_NO_EC */
+
+
 OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config\n")
 
 int setup_tests(void)
@@ -7730,13 +7862,19 @@ int setup_tests(void)
 
     cert = test_mk_file_path(certsdir, "servercert.pem");
     if (cert == NULL)
-        return 0;
+        goto err;
 
     privkey = test_mk_file_path(certsdir, "serverkey.pem");
-    if (privkey == NULL) {
-        OPENSSL_free(cert);
-        return 0;
-    }
+    if (privkey == NULL)
+        goto err;
+
+    cert2 = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
+    if (cert2 == NULL)
+        goto err;
+
+    privkey2 = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
+    if (privkey2 == NULL)
+        goto err;
 
 #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) \
     && !defined(OPENSSL_NO_SOCK)
@@ -7859,13 +7997,25 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_multiblock_write, OSSL_NELEM(multiblock_cipherlist_data));
 #endif
     ADD_ALL_TESTS(test_servername, 10);
+#ifndef OPENSSL_NO_EC
+    ADD_ALL_TESTS(test_sigalgs_available, 6);
+#endif
     return 1;
+
+ err:
+    OPENSSL_free(cert);
+    OPENSSL_free(privkey);
+    OPENSSL_free(cert2);
+    OPENSSL_free(privkey2);
+    return 0;
 }
 
 void cleanup_tests(void)
 {
     OPENSSL_free(cert);
     OPENSSL_free(privkey);
+    OPENSSL_free(cert2);
+    OPENSSL_free(privkey2);
     bio_s_mempacket_test_free();
     bio_s_always_retry_free();
     OSSL_PROVIDER_unload(defctxnull);
diff --git a/test/ssltestlib.c b/test/ssltestlib.c
index ce0e776110..96c1a7f2de 100644
--- a/test/ssltestlib.c
+++ b/test/ssltestlib.c
@@ -741,8 +741,10 @@ const SSL_METHOD *cm,
     return 1;
 
  err:
-    SSL_CTX_free(serverctx);
-    SSL_CTX_free(clientctx);
+    if (*sctx == NULL)
+        SSL_CTX_free(serverctx);
+    if (cctx != NULL && *cctx == NULL)
+        SSL_CTX_free(clientctx);
     return 0;
 }
 
diff --git a/util/libcrypto.num b/util/libcrypto.num
index fd0509172f..a34d467099 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5097,3 +5097,5 @@ EC_GROUP_get_field_type                 ?	3_0_0	EXIST::FUNCTION:EC
 X509_PUBKEY_eq                          ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_eq                             ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_parameters_eq                  ?	3_0_0	EXIST::FUNCTION:
+OSSL_PROVIDER_query_operation           ?	3_0_0	EXIST::FUNCTION:
+OSSL_PROVIDER_get0_provider_ctx         ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list