Create the SSL object for QUIC-TLS
authorMatt Caswell <matt@openssl.org>
Tue, 8 Nov 2022 16:20:08 +0000 (16:20 +0000)
committerMatt Caswell <matt@openssl.org>
Tue, 24 Jan 2023 17:16:29 +0000 (17:16 +0000)
The "user" SSL object which represents the QUIC connection should have an
"inner" SSL object to represent the TLS connection.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19748)

ssl/quic/quic_impl.c
ssl/ssl_conf.c
ssl/ssl_lib.c
ssl/ssl_local.h
ssl/ssl_sess.c
ssl/statem/statem_lib.c

index d6c91164978cfa13e9a74262eb032856b1e416ed..44e05754d47f84f9c6dfc0c177eaf429d1fd0c10 100644 (file)
@@ -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 */
index 0bea29fb66cf31884c9183989950ddcbe38552f9..b46b5f15d934f2ea1f51ffb4cea379fd4184993b 100644 (file)
@@ -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)
index deb040e5efd459bb67897e16246350951686b456..1a5bc6d3e40b285f84771abe43b1cd21ef16d461 100644 (file)
@@ -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;
index da01e904a30c32669a485235be86ecc994968395..fabf844601dc7aaf21020c07dc80dddd69e1c440 100644 (file)
@@ -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);
index fbc3224219a40fe20dcfadd14b2c44706004e60c..7f9bafb0d3ea5dc23d5718d25ba8229d2e821046 100644 (file)
@@ -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;
     }
 
index 10e6ef9edd58b38fad7af89158e8d40716a02f65..40ca9a15e9c10f28104040bfbddf8e7d0d7581ca 100644 (file)
@@ -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. */