Home | History | Annotate | Line # | Download | only in quic
      1 /*
      2  * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #ifndef OSSL_QUIC_OBJ_LOCAL_H
     11 #define OSSL_QUIC_OBJ_LOCAL_H
     12 
     13 #include <openssl/ssl.h>
     14 #include "internal/quic_predef.h"
     15 #include "internal/quic_engine.h"
     16 #include "../ssl_local.h"
     17 
     18 #ifndef OPENSSL_NO_QUIC
     19 
     20 /*
     21  * QUIC Object Structure.
     22  *
     23  * In the libssl APL, we have QLSOs, QCSOs and QSSOs, and in the future might
     24  * choose to introduce QDSOs. There are also roles such as Port Leader and Event
     25  * Leader which can be assumed by these different types under different
     26  * circumstances  in other words, whether an APL object is a Port or Event
     27  * Leader is not a static function of its type and these roles can 'float'
     28  * dynamically depending on the circumstances under which an APL object was
     29  * created.
     30  *
     31  * The QUIC_OBJ is a base type for QUIC APL objects which provides functionality
     32  * common to all QUIC objects and which supports having different APL objects
     33  * dynamically assume leader roles. It can therefore be seen as an extension of
     34  * the SSL base class and extends the SSL object for QUIC APL objects. This
     35  * avoids duplication of functionality for different types of QUIC object and
     36  * allows access to common responsibilities of different types of APL object
     37  * without regard to the kind of APL object we are dealing with.
     38  *
     39  * The "inheritance" hierarchy is as follows:
     40  *
     41  *   SSL
     42  *      SSL_CONNECTION
     43  *      QUIC_OBJ
     44  *          QUIC_DOMAIN         (QDSO) -> QUIC_ENGINE  *E
     45  *          QUIC_LISTENER       (QLSO) -> QUIC_PORT     eP
     46  *          QUIC_CONNECTION     (QCSO) -> QUIC_CHANNEL  epCs
     47  *          QUIC_XSO            (QSSO) -> QUIC_STREAM      S
     48  *
     49  * Legend:
     50  *
     51  *   *: Not currently modelled in the APL, though QUIC_ENGINE exists internally.
     52  *
     53  *   E: Always an event leader if it exists.
     54  *   e: Potentially an event leader (namely if it is the root APL object in a
     55  *      hierarchy).
     56  *
     57  *   P: Always a port leader if it exists.
     58  *   p: Potentially a port leader (namely if there is no port leader above it).
     59  *
     60  *   C: Always a connection leader.
     61  *
     62  *   s: Potentially usable as a stream (if it has a default stream attached).
     63  *   S: Always has the stream role if it exists.
     64  *
     65  * This structure must come at the start of a QUIC object structure definition.
     66  *
     67  * ssl->type still determines the actual object type. An SSL object
     68  * pointer s can be safely cast to (QUIC_OBJ *) iff IS_QUIC(s) is true.
     69  */
     70 struct quic_obj_st {
     71     /* SSL object common header. */
     72     struct ssl_st ssl;
     73 
     74     /*
     75      * Pointer to a parent APL object in a QUIC APL object hierarchy, or NULL if
     76      * this is the root object.
     77      */
     78     QUIC_OBJ *parent_obj;
     79 
     80     /* invariant: != NULL */
     81     QUIC_OBJ *cached_event_leader;
     82     /* invariant: != NULL iff this is a port leader or subsidiary object */
     83     QUIC_OBJ *cached_port_leader;
     84 
     85     /*
     86      * Points to the QUIC_ENGINE instance. Always equals
     87      * cached_event_leader->engine. The containing_obj APL object owns this
     88      * instance iff is_event_leader is set, otherwise it is an additional
     89      * reference cached for convenience. Unlike port this is never NULL because
     90      * a QUIC domain is always rooted in an event leader.
     91      */
     92     QUIC_ENGINE *engine;
     93 
     94     /*
     95      * Points to the QUIC_PORT instance applicable to the containing_obj APL
     96      * object, or NULL if we are not at or below a port leader. Always equals
     97      * cached_port_leader->port. The containing_obj APL object owns this
     98      * instance iff is_port_leader is set, otherwise it is an additional
     99      * reference cached for convenience.
    100      */
    101     QUIC_PORT *port;
    102 
    103     /* SSL_DOMAIN_FLAG values taken from SSL_CTX at construction time. */
    104     uint64_t domain_flags;
    105 
    106     unsigned int init_done : 1;
    107     unsigned int is_event_leader : 1;
    108     unsigned int is_port_leader : 1;
    109 
    110     /*
    111      * Blocking mode configuration is handled generically through QUIC_OBJ as it
    112      * by default inherits from the parent SSL object.
    113      */
    114     unsigned int req_blocking_mode : 2; /* QUIC_BLOCKING_MODE */
    115 
    116     /* Event handling mode. One of SSL_QUIC_VALUE_EVENT_HANDLING. */
    117     unsigned int event_handling_mode : 2;
    118 };
    119 
    120 enum {
    121     QUIC_BLOCKING_MODE_INHERIT,
    122     QUIC_BLOCKING_MODE_NONBLOCKING,
    123     QUIC_BLOCKING_MODE_BLOCKING
    124 };
    125 
    126 /*
    127  * Core Functions and Inlines
    128  * ==========================
    129  */
    130 
    131 /*
    132  * Initialises a QUIC_OBJ structure with zero or more roles active. Returns 1
    133  * on success or 0 on failure.
    134  *
    135  * ctx: A SSL_CTX used to initialise the SSL base object structure.
    136  *
    137  * type: A SSL_TYPE_* value designating the SSL object type.
    138  *
    139  * parent_obj: NULL if this is the root APL object in a new hierarchy, or a
    140  * pointer to the parent APL object otherwise.
    141  *
    142  * engine: If non-NULL, this object becomes the Event Leader. parent_obj must be
    143  * NULL iff this is non-NULL as currently the Event Leader is always the root in
    144  * an APL object hierarchy. If NULL, the contextually applicable engine is
    145  * determined by using parent_obj and ancestors to find the Event Leader.
    146  *
    147  * port: If non-NULL, this object becomes a Port Leader. If NULL, the
    148  * contextually applicable port (if any) is determined by using parent_obj and
    149  * ancestors to find the Port Leader.
    150  */
    151 int ossl_quic_obj_init(QUIC_OBJ *obj,
    152     SSL_CTX *ctx,
    153     int type,
    154     SSL *parent_obj,
    155     QUIC_ENGINE *engine,
    156     QUIC_PORT *port);
    157 
    158 /*
    159  * Returns a pointer to the handshake layer object which should be accessible on
    160  * obj for purposes of handshake API autoforwarding, if any.
    161  *
    162  * This returns NULL if a handshake layer SSL object is available but should not
    163  * be used for autoforwarding purposes, for example on a QSSO.
    164  */
    165 SSL_CONNECTION *ossl_quic_obj_get0_handshake_layer(QUIC_OBJ *obj);
    166 
    167 /*
    168  * Returns a pointer to the SSL base object structure. Returns NULL if obj is
    169  * NULL. If obj is non-NULL, it must be initialised.
    170  */
    171 static ossl_inline ossl_unused SSL *
    172 ossl_quic_obj_get0_ssl(QUIC_OBJ *obj)
    173 {
    174     /*
    175      * ->ssl is guaranteed to have an offset of 0 but the NULL check here makes
    176      *  ubsan happy.
    177      */
    178     if (!ossl_assert(obj != NULL))
    179         return NULL;
    180 
    181     return &obj->ssl;
    182 }
    183 
    184 /*
    185  * Determines the applicable engine and return a pointer to it. Never returns
    186  * NULL.
    187  */
    188 static ossl_inline ossl_unused QUIC_ENGINE *
    189 ossl_quic_obj_get0_engine(const QUIC_OBJ *obj)
    190 {
    191     assert(obj->init_done);
    192     assert(obj->engine != NULL);
    193     return obj->engine;
    194 }
    195 
    196 /* Determines the applicable port (if any) and returns a pointer to it. */
    197 static ossl_inline ossl_unused QUIC_PORT *
    198 ossl_quic_obj_get0_port(const QUIC_OBJ *obj)
    199 {
    200     assert(obj->init_done);
    201     return obj->port;
    202 }
    203 
    204 /* Returns 1 iff this leader structure represents an event leader. */
    205 static ossl_inline ossl_unused int
    206 ossl_quic_obj_is_event_leader(const QUIC_OBJ *obj)
    207 {
    208     return obj->is_event_leader;
    209 }
    210 
    211 /*
    212  * Similar to ossl_quic_obj_get0_engine, but only returns a non-NULL value if
    213  * the obj object itself is an event leader, rather than one of its ancestors.
    214  */
    215 static ossl_inline ossl_unused QUIC_ENGINE *
    216 ossl_quic_obj_get0_engine_local(const QUIC_OBJ *obj)
    217 {
    218     return ossl_quic_obj_is_event_leader(obj)
    219         ? ossl_quic_obj_get0_engine(obj)
    220         : NULL;
    221 }
    222 
    223 /* Returns 1 iff this leader structure represents a port leader. */
    224 static ossl_inline ossl_unused int
    225 ossl_quic_obj_is_port_leader(const QUIC_OBJ *obj)
    226 {
    227     return obj->is_port_leader;
    228 }
    229 
    230 /*
    231  * Similar to ossl_quic_obj_get0_port, but only returns a non-NULL value if
    232  * the obj object itself is a port leader, rather than one of its ancestors.
    233  */
    234 static ossl_inline ossl_unused QUIC_PORT *
    235 ossl_quic_obj_get0_port_local(const QUIC_OBJ *obj)
    236 {
    237     return ossl_quic_obj_is_port_leader(obj)
    238         ? ossl_quic_obj_get0_port(obj)
    239         : NULL;
    240 }
    241 
    242 /*
    243  * Return 1 if we are currently capable of supporting blocking mode (regardless
    244  * of whether it is actually turned on).
    245  */
    246 int ossl_quic_obj_can_support_blocking(const QUIC_OBJ *obj);
    247 
    248 /*
    249  * Returns 1 if we *desire* to do blocking I/O, regardless of whether it will
    250  * actually be used (e.g. because it cannot currently be supported).
    251  */
    252 int ossl_quic_obj_desires_blocking(const QUIC_OBJ *obj);
    253 
    254 /*
    255  * Return 1 if an API call directly to the given object should use blocking mode
    256  * and 0 otherwise.
    257  */
    258 int ossl_quic_obj_blocking(const QUIC_OBJ *obj);
    259 
    260 /*
    261  * Set the (requested) blocking mode, which might or might not be honoured
    262  * depending on whether the BIO configuration can support it. Argument is a
    263  * QUIC_BLOCKING_MODE value. If the top-level object in a QSO hierarchy is set
    264  * to QUIC_BLOCKING_MODE_INHERIT, defaults to blocking mode.
    265  */
    266 void ossl_quic_obj_set_blocking_mode(QUIC_OBJ *obj, unsigned int mode);
    267 
    268 /*
    269  * Convenience Inlines
    270  * ===================
    271  *
    272  * These inlines are expressed in terms of the core functions and inlines above.
    273  */
    274 
    275 /* Get a pointer to the QUIC domain mutex. Always returns non-NULL. */
    276 static ossl_inline ossl_unused CRYPTO_MUTEX *
    277 ossl_quic_obj_get0_mutex(const QUIC_OBJ *obj)
    278 {
    279     return ossl_quic_engine_get0_mutex(ossl_quic_obj_get0_engine(obj));
    280 }
    281 
    282 /*
    283  * Get a reference to the reactor applicable to a leader. Always returns
    284  * non-NULL.
    285  */
    286 static ossl_inline ossl_unused QUIC_REACTOR *
    287 ossl_quic_obj_get0_reactor(const QUIC_OBJ *obj)
    288 {
    289     return ossl_quic_engine_get0_reactor(ossl_quic_obj_get0_engine(obj));
    290 }
    291 
    292 /* Get a reference to the OSSL_LIB_CTX pointer applicable to a leader. */
    293 static ossl_inline ossl_unused OSSL_LIB_CTX *
    294 ossl_quic_obj_get0_libctx(const QUIC_OBJ *obj)
    295 {
    296     return ossl_quic_engine_get0_libctx(ossl_quic_obj_get0_engine(obj));
    297 }
    298 
    299 /* Get a reference to the propq pointer applicable to a leader. */
    300 static ossl_inline ossl_unused const char *
    301 ossl_quic_obj_get0_propq(const QUIC_OBJ *obj)
    302 {
    303     return ossl_quic_engine_get0_propq(ossl_quic_obj_get0_engine(obj));
    304 }
    305 
    306 /*
    307  * Returns the APL object pointer to the event leader in a hierarchy. Always
    308  * returns non-NULL.
    309  */
    310 static ossl_inline ossl_unused SSL *
    311 ossl_quic_obj_get0_event_leader(const QUIC_OBJ *obj)
    312 {
    313     assert(obj->init_done);
    314     return obj->cached_event_leader != NULL
    315         ? &obj->cached_event_leader->ssl
    316         : NULL;
    317 }
    318 
    319 /*
    320  * Returns the APL object pointer to the port leader in a hierarchy (if any).
    321  * Always returns non-NULL.
    322  */
    323 static ossl_inline ossl_unused SSL *
    324 ossl_quic_obj_get0_port_leader(const QUIC_OBJ *obj)
    325 {
    326     assert(obj->init_done);
    327     return obj->cached_port_leader != NULL
    328         ? &obj->cached_port_leader->ssl
    329         : NULL;
    330 }
    331 
    332 /*
    333  * Change the domain flags. Should only be called immediately after
    334  * ossl_quic_obj_init().
    335  */
    336 static ossl_inline ossl_unused void
    337 ossl_quic_obj_set_domain_flags(QUIC_OBJ *obj, uint64_t domain_flags)
    338 {
    339     obj->domain_flags = domain_flags;
    340 }
    341 
    342 #endif
    343 #endif
    344