From a7f41885b368c7fb63e52aadaa0a5b5bd239b876 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 8 Nov 2022 16:20:08 +0000 Subject: [PATCH 1/1] Create the SSL object for QUIC-TLS The "user" SSL object which represents the QUIC connection should have an "inner" SSL object to represent the TLS connection. Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19748) --- ssl/quic/quic_impl.c | 12 +++++++++++- ssl/ssl_conf.c | 2 +- ssl/ssl_lib.c | 27 ++++++++++++++++----------- ssl/ssl_local.h | 8 +++++--- ssl/ssl_sess.c | 4 ++-- ssl/statem/statem_lib.c | 10 +++++----- 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index d6c9116497..44e05754d4 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -118,6 +118,7 @@ SSL *ossl_quic_new(SSL_CTX *ctx) { QUIC_CONNECTION *qc = NULL; SSL *ssl_base = NULL; + SSL_CONNECTION *sc = NULL; qc = OPENSSL_zalloc(sizeof(*qc)); if (qc == NULL) @@ -125,15 +126,22 @@ SSL *ossl_quic_new(SSL_CTX *ctx) /* Initialise the QUIC_CONNECTION's stub header. */ ssl_base = &qc->ssl; - if (!ossl_ssl_init(ssl_base, ctx, SSL_TYPE_QUIC_CONNECTION)) { + if (!ossl_ssl_init(ssl_base, ctx, ctx->method, SSL_TYPE_QUIC_CONNECTION)) { ssl_base = NULL; goto err; } + qc->tls = ossl_ssl_connection_new_int(ctx, TLS_client_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; + /* Channel is not created yet. */ qc->ssl_mode = qc->ssl.ctx->mode; qc->last_error = SSL_ERROR_NONE; qc->blocking = 1; + return ssl_base; err: @@ -156,6 +164,8 @@ void ossl_quic_free(SSL *s) BIO_free(qc->net_wbio); /* Note: SSL_free calls OPENSSL_free(qc) for us */ + + SSL_free(qc->tls); } /* SSL method init */ diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 0bea29fb66..b46b5f15d9 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -337,7 +337,7 @@ static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound) if (cctx->ctx != NULL) method_version = cctx->ctx->method->version; else if (cctx->ssl != NULL) - method_version = cctx->ssl->ctx->method->version; + method_version = cctx->ssl->defltmeth->version; else return 0; if ((new_version = protocol_from_string(value)) < 0) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index deb040e5ef..1a5bc6d3e4 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -644,9 +644,9 @@ int ossl_ssl_connection_reset(SSL *s) * Check to see if we were changed into a different method, if so, revert * back. */ - if (s->method != SSL_CONNECTION_GET_CTX(sc)->method) { + if (s->method != s->defltmeth) { s->method->ssl_deinit(s); - s->method = SSL_CONNECTION_GET_CTX(sc)->method; + s->method = s->defltmeth; if (!s->method->ssl_init(s)) return 0; } else { @@ -702,7 +702,7 @@ SSL *SSL_new(SSL_CTX *ctx) return ctx->method->ssl_new(ctx); } -int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, int type) +int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, const SSL_METHOD *method, int type) { ssl->type = type; @@ -714,7 +714,7 @@ int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, int type) SSL_CTX_up_ref(ctx); ssl->ctx = ctx; - ssl->method = ctx->method; + ssl->defltmeth = ssl->method = method; if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, ssl, &ssl->ex_data)) return 0; @@ -722,7 +722,7 @@ int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, int type) return 1; } -SSL *ossl_ssl_connection_new(SSL_CTX *ctx) +SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method) { SSL_CONNECTION *s; SSL *ssl; @@ -732,7 +732,7 @@ SSL *ossl_ssl_connection_new(SSL_CTX *ctx) return NULL; ssl = &s->ssl; - if (!ossl_ssl_init(ssl, ctx, SSL_TYPE_SSL_CONNECTION)) { + if (!ossl_ssl_init(ssl, ctx, method, SSL_TYPE_SSL_CONNECTION)) { OPENSSL_free(s); s = NULL; goto sslerr; @@ -860,12 +860,12 @@ SSL *ossl_ssl_connection_new(SSL_CTX *ctx) s->allow_early_data_cb = ctx->allow_early_data_cb; s->allow_early_data_cb_data = ctx->allow_early_data_cb_data; - if (!ssl->method->ssl_init(ssl)) + if (!method->ssl_init(ssl)) goto sslerr; - s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1; + s->server = (method->ssl_accept == ssl_undefined_function) ? 0 : 1; - if (!SSL_clear(ssl)) + if (!method->ssl_reset(ssl)) goto sslerr; #ifndef OPENSSL_NO_PSK @@ -904,6 +904,11 @@ SSL *ossl_ssl_connection_new(SSL_CTX *ctx) return NULL; } +SSL *ossl_ssl_connection_new(SSL_CTX *ctx) +{ + return ossl_ssl_connection_new_int(ctx, ctx->method); +} + int SSL_is_dtls(const SSL *s) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s); @@ -2887,13 +2892,13 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) return 0; case SSL_CTRL_SET_MIN_PROTO_VERSION: return ssl_check_allowed_versions(larg, sc->max_proto_version) - && ssl_set_version_bound(s->ctx->method->version, (int)larg, + && ssl_set_version_bound(s->defltmeth->version, (int)larg, &sc->min_proto_version); case SSL_CTRL_GET_MIN_PROTO_VERSION: return sc->min_proto_version; case SSL_CTRL_SET_MAX_PROTO_VERSION: return ssl_check_allowed_versions(sc->min_proto_version, larg) - && ssl_set_version_bound(s->ctx->method->version, (int)larg, + && ssl_set_version_bound(s->defltmeth->version, (int)larg, &sc->max_proto_version); case SSL_CTRL_GET_MAX_PROTO_VERSION: return sc->max_proto_version; diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index da01e904a3..fabf844601 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -1238,6 +1238,7 @@ typedef struct cert_pkey_st CERT_PKEY; struct ssl_st { int type; SSL_CTX *ctx; + const SSL_METHOD *defltmeth; const SSL_METHOD *method; CRYPTO_REF_COUNT references; CRYPTO_RWLOCK *lock; @@ -1841,6 +1842,7 @@ struct ssl_connection_st { # define SSL_CONNECTION_FROM_CONST_SSL_ONLY(ssl) \ SSL_CONNECTION_FROM_SSL_ONLY_int(ssl, const) # define SSL_CONNECTION_GET_CTX(sc) ((sc)->ssl.ctx) +# define SSL_CONNECTION_GET_SSL(sc) (&(sc)->ssl) # ifndef OPENSSL_NO_QUIC # include "quic/quic_local.h" # define SSL_CONNECTION_FROM_SSL_int(ssl, c) \ @@ -1854,13 +1856,11 @@ struct ssl_connection_st { SSL_CONNECTION_FROM_SSL_int(ssl, SSL_CONNECTION_NO_CONST) # define SSL_CONNECTION_FROM_CONST_SSL(ssl) \ SSL_CONNECTION_FROM_SSL_int(ssl, const) -# define SSL_CONNECTION_GET_SSL(sc) ((sc)->user_ssl) # else # define SSL_CONNECTION_FROM_SSL(ssl) \ SSL_CONNECTION_FROM_SSL_ONLY_int(ssl, SSL_CONNECTION_NO_CONST) # define SSL_CONNECTION_FROM_CONST_SSL(ssl) \ SSL_CONNECTION_FROM_SSL_ONLY_int(ssl, const) -# define SSL_CONNECTION_GET_SSL(sc) (&(sc)->ssl) # endif /* @@ -2465,7 +2465,9 @@ static ossl_inline void tls1_get_peer_groups(SSL_CONNECTION *s, # ifndef OPENSSL_UNIT_TEST -__owur int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, int type); +__owur int ossl_ssl_init(SSL *ssl, SSL_CTX *ctx, const SSL_METHOD *method, + int type); +__owur SSL *ossl_ssl_connection_new_int(SSL_CTX *ctx, const SSL_METHOD *method); __owur SSL *ossl_ssl_connection_new(SSL_CTX *ctx); void ossl_ssl_connection_free(SSL *ssl); __owur int ossl_ssl_connection_reset(SSL *ssl); diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index fbc3224219..7f9bafb0d3 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -854,8 +854,8 @@ int SSL_set_session(SSL *s, SSL_SESSION *session) return 0; ssl_clear_bad_session(sc); - if (s->ctx->method != s->method) { - if (!SSL_set_ssl_method(s, s->ctx->method)) + if (s->defltmeth != s->method) { + if (!SSL_set_ssl_method(s, s->defltmeth)) return 0; } diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 10e6ef9edd..40ca9a15e9 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1657,23 +1657,23 @@ int ssl_check_version_downgrade(SSL_CONNECTION *s) { const version_info *vent; const version_info *table; - SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + SSL *ssl = SSL_CONNECTION_GET_SSL(s); /* * Check that the current protocol is the highest enabled version - * (according to s->ctx->method, as version negotiation may have changed + * (according to ssl->defltmethod, as version negotiation may have changed * s->method). */ - if (s->version == sctx->method->version) + if (s->version == ssl->defltmeth->version) return 1; /* * Apparently we're using a version-flexible SSL_METHOD (not at its * highest protocol version). */ - if (sctx->method->version == TLS_method()->version) + if (ssl->defltmeth->version == TLS_method()->version) table = tls_version_table; - else if (sctx->method->version == DTLS_method()->version) + else if (ssl->defltmeth->version == DTLS_method()->version) table = dtls_version_table; else { /* Unexpected state; fail closed. */ -- 2.34.1