__owur int ossl_quic_get_key_update_type(const SSL *s);
__owur int ossl_quic_num_ciphers(void);
__owur const SSL_CIPHER *ossl_quic_get_cipher(unsigned int u);
-__owur int ossl_quic_set_ssl_op(SSL *ssl, uint64_t op);
int ossl_quic_renegotiate_check(SSL *ssl, int initok);
typedef struct quic_conn_st QUIC_CONNECTION;
SSL_CONN_CLOSE_INFO *info,
size_t info_len);
+uint64_t ossl_quic_set_options(SSL *s, uint64_t opts);
+uint64_t ossl_quic_clear_options(SSL *s, uint64_t opts);
+uint64_t ossl_quic_get_options(const SSL *s);
+
/*
* Used to override ossl_time_now() for debug purposes. While this may be
* overridden at any time, expect strange results if you change it after
* ossl_quic_deinit
* SSL_free => ossl_quic_free
*
+ * SSL_set_options => ossl_quic_set_options
+ * SSL_get_options => ossl_quic_get_options
+ * SSL_clear_options => ossl_quic_clear_options
+ *
*/
/* SSL_new */
qc->tls = ossl_ssl_connection_new_int(ctx, TLS_method());
if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL)
goto err;
+
/* override the user_ssl of the inner connection */
- sc->user_ssl = ssl_base;
sc->s3.flags |= TLS1_FLAGS_QUIC;
+ /* Restrict options derived from the SSL_CTX. */
+ sc->options &= OSSL_QUIC_PERMITTED_OPTIONS;
+
#if defined(OPENSSL_THREADS)
if ((qc->mutex = ossl_crypto_mutex_new()) == NULL)
goto err;
SSL_free(&old_xso->ssl);
}
+/* SSL_set_options */
+static uint64_t quic_mask_or_options(SSL *ssl, uint64_t mask_value, uint64_t or_value)
+{
+ QCTX ctx;
+ uint64_t r, options;
+
+ if (!expect_quic_with_stream_lock(ssl, /*remote_init=*/-1, &ctx))
+ return 0;
+
+ /*
+ * Currently most options that we permit are handled in the handshake
+ * layer.
+ */
+ options = (SSL_get_options(ctx.qc->tls) & ~mask_value) | or_value;
+ options &= OSSL_QUIC_PERMITTED_OPTIONS;
+ r = SSL_set_options(ctx.qc->tls, options);
+
+ if (ctx.xso->stream != NULL && ctx.xso->stream->rstream != NULL)
+ ossl_quic_rstream_set_cleanse(ctx.xso->stream->rstream,
+ (options & SSL_OP_CLEANSE_PLAINTEXT) != 0);
+
+ quic_unlock(ctx.qc);
+ return r;
+}
+
+uint64_t ossl_quic_set_options(SSL *ssl, uint64_t options)
+{
+ return quic_mask_or_options(ssl, UINT64_MAX, options);
+}
+
+/* SSL_clear_options */
+uint64_t ossl_quic_clear_options(SSL *ssl, uint64_t options)
+{
+ return quic_mask_or_options(ssl, options, 0);
+}
+
+/* SSL_get_options */
+uint64_t ossl_quic_get_options(const SSL *ssl)
+{
+ return quic_mask_or_options((SSL *)ssl, 0, 0);
+}
+
/*
* QUIC Front-End I/O API: Network BIO Configuration
* =================================================
RECORD_LAYER_init(&s->rlayer, s);
s->options = ctx->options;
+
s->dane.flags = ctx->dane.flags;
if (method->version == ctx->method->version) {
s->min_proto_version = ctx->min_proto_version;
{
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s);
+#ifndef OPENSSL_NO_QUIC
+ if (IS_QUIC(s))
+ return ossl_quic_get_options(s);
+#endif
+
if (sc == NULL)
return 0;
OSSL_PARAM options[2], *opts = options;
#ifndef OPENSSL_NO_QUIC
- if (IS_QUIC(s) && ossl_quic_set_ssl_op(s, op))
- /* Handled by QUIC, return as set */
- return op;
+ if (IS_QUIC(s))
+ return ossl_quic_set_options(s, op);
#endif
- sc = SSL_CONNECTION_FROM_SSL(s);
- if (sc == NULL)
+ sc = SSL_CONNECTION_FROM_SSL(s);
+ if (sc == NULL)
return 0;
sc->options |= op;
{
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
+#ifndef OPENSSL_NO_QUIC
+ if (IS_QUIC(s))
+ return ossl_quic_clear_options(s, op);
+#endif
+
if (sc == NULL)
return 0;
const OSSL_RECORD_METHOD *meth,
void *rlarg);
+/*
+ * Options which no longer have any effect, but which can be implemented
+ * as no-ops for QUIC.
+ */
+#define OSSL_LEGACY_SSL_OPTIONS \
+ (SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG | \
+ SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER | \
+ SSL_OP_SSLEAY_080_CLIENT_DH_BUG | \
+ SSL_OP_TLS_D5_BUG | \
+ SSL_OP_TLS_BLOCK_PADDING_BUG | \
+ SSL_OP_MSIE_SSLV2_RSA_PADDING | \
+ SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG | \
+ SSL_OP_MICROSOFT_SESS_ID_BUG | \
+ SSL_OP_NETSCAPE_CHALLENGE_BUG | \
+ SSL_OP_PKCS1_CHECK_1 | \
+ SSL_OP_PKCS1_CHECK_2 | \
+ SSL_OP_SINGLE_DH_USE | \
+ SSL_OP_SINGLE_ECDH_USE | \
+ SSL_OP_EPHEMERAL_RSA )
+
+/*
+ * Options which are no-ops under QUIC or TLSv1.3 and which are therefore
+ * allowed but ignored under QUIC.
+ */
+#define OSSL_TLS1_2_OPTIONS \
+ (SSL_OP_CRYPTOPRO_TLSEXT_BUG | \
+ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS | \
+ SSL_OP_ALLOW_CLIENT_RENEGOTIATION | \
+ SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION | \
+ SSL_OP_NO_COMPRESSION | \
+ SSL_OP_NO_SSLv3 | \
+ SSL_OP_NO_TLSv1 | \
+ SSL_OP_NO_TLSv1_1 | \
+ SSL_OP_NO_TLSv1_2 | \
+ SSL_OP_NO_DTLSv1 | \
+ SSL_OP_NO_DTLSv1_2 | \
+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | \
+ SSL_OP_CISCO_ANYCONNECT | \
+ SSL_OP_NO_RENEGOTIATION | \
+ SSL_OP_NO_EXTENDED_MASTER_SECRET | \
+ SSL_OP_NO_ENCRYPT_THEN_MAC | \
+ SSL_OP_COOKIE_EXCHANGE | \
+ SSL_OP_LEGACY_SERVER_CONNECT | \
+ SSL_OP_IGNORE_UNEXPECTED_EOF )
+
+/* Total mask of options permitted or ignored under QUIC. */
+#define OSSL_QUIC_PERMITTED_OPTIONS \
+ (OSSL_LEGACY_SSL_OPTIONS | \
+ OSSL_TLS1_2_OPTIONS | \
+ SSL_OP_CIPHER_SERVER_PREFERENCE | \
+ SSL_OP_DISABLE_TLSEXT_CA_NAMES | \
+ SSL_OP_NO_TX_CERTIFICATE_COMPRESSION | \
+ SSL_OP_NO_RX_CERTIFICATE_COMPRESSION | \
+ SSL_OP_PRIORITIZE_CHACHA | \
+ SSL_OP_CLEANSE_PLAINTEXT | \
+ SSL_OP_NO_QUERY_MTU | \
+ SSL_OP_NO_TICKET | \
+ SSL_OP_NO_ANTI_REPLAY )
+
#endif
#include "helpers/quictestlib.h"
#include "testutil.h"
#include "testutil/output.h"
+#include "../ssl/ssl_local.h"
static OSSL_LIB_CTX *libctx = NULL;
static OSSL_PROVIDER *defctxnull = NULL;
return testresult;
}
+static int test_quic_forbidden_options(void)
+{
+ int testresult = 0;
+ SSL_CTX *ctx = NULL;
+ SSL *ssl = NULL;
+
+ if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method())))
+ goto err;
+
+ /* QUIC options restrictions do not affect SSL_CTX */
+ SSL_CTX_set_options(ctx, UINT64_MAX);
+
+ if (!TEST_uint64_t_eq(SSL_CTX_get_options(ctx), UINT64_MAX))
+ goto err;
+
+ if (!TEST_ptr(ssl = SSL_new(ctx)))
+ goto err;
+
+ /* Only permitted options get transferred to SSL object */
+ if (!TEST_uint64_t_eq(SSL_get_options(ssl), OSSL_QUIC_PERMITTED_OPTIONS))
+ goto err;
+
+ /* Try again using SSL_set_options */
+ SSL_set_options(ssl, UINT64_MAX);
+
+ if (!TEST_uint64_t_eq(SSL_get_options(ssl), OSSL_QUIC_PERMITTED_OPTIONS))
+ goto err;
+
+ /* Clear everything */
+ SSL_clear_options(ssl, UINT64_MAX);
+
+ if (!TEST_uint64_t_eq(SSL_get_options(ssl), 0))
+ goto err;
+
+ testresult = 1;
+err:
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ return testresult;
+}
+
OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n")
int setup_tests(void)
#endif
ADD_TEST(test_quic_forbidden_apis_ctx);
ADD_TEST(test_quic_forbidden_apis);
+ ADD_TEST(test_quic_forbidden_options);
return 1;
err:
cleanup_tests();