[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