summaryrefslogtreecommitdiffstats
path: root/ssl/quic/quic_obj_local.h
blob: d0cfa4165b5e6e4fc05e870d3aa957ee4a4f3552 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 * Copyright 2024 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
 */

#ifndef OSSL_QUIC_OBJ_LOCAL_H
# define OSSL_QUIC_OBJ_LOCAL_H

# include <openssl/ssl.h>
# include "internal/quic_predef.h"
# include "internal/quic_engine.h"
# include "../ssl_local.h"

# ifndef OPENSSL_NO_QUIC

/*
 * QUIC Object Structure.
 *
 * In the libssl APL, we have QLSOs, QCSOs and QSSOs, and in the future might
 * choose to introduce QDSOs. There are also roles such as Port Leader and Event
 * Leader which can be assumed by these different types under different
 * circumstances — in other words, whether an APL object is a Port or Event
 * Leader is not a static function of its type and these roles can 'float'
 * dynamically depending on the circumstances under which an APL object was
 * created.
 *
 * The QUIC_OBJ is a base type for QUIC APL objects which provides functionality
 * common to all QUIC objects and which supports having different APL objects
 * dynamically assume leader roles. It can therefore be seen as an extention of
 * the SSL base class and extends the SSL object for QUIC APL objects. This
 * avoids duplication of functionality for different types of QUIC object and
 * allows access to common responsibilities of different types of APL object
 * without regard to the kind of APL object we are dealing with.
 *
 * The "inheritance" hierarchy is as follows:
 *
 *   SSL
 *      SSL_CONNECTION
 *      QUIC_OBJ
 *          QUIC_DOMAIN         (QDSO) -> QUIC_ENGINE  *E
 *          QUIC_LISTENER       (QLSO) -> QUIC_PORT     eP
 *          QUIC_CONNECTION     (QCSO) -> QUIC_CHANNEL  epCs
 *          QUIC_XSO            (QSSO) -> QUIC_STREAM      S
 *
 * Legend:
 *
 *   *: Not currently modelled in the APL, though QUIC_ENGINE exists internally.
 *
 *   E: Always an event leader if it exists.
 *   e: Potentially an event leader (namely if it is the root APL object in a
 *      hierarchy).
 *
 *   P: Always a port leader if it exists.
 *   p: Potentially a port leader (namely if there is no port leader above it).
 *
 *   C: Always a connection leader.
 *
 *   s: Potentially usable as a stream (if it has a default stream attached).
 *   S: Always has the stream role if it exists.
 *
 * This structure must come at the start of a QUIC object structure definition.
 *
 * ssl->type still determines the actual object type. An SSL object pointer s
 * can be safely cast to (QUIC_OBJ *) iff IS_QUIC(s) is true.
 */
struct quic_obj_st {
    /* SSL object common header. */
    struct ssl_st           ssl;

    /*
     * Pointer to a parent APL object in a QUIC APL object hierarchy, or NULL if
     * this is the root object.
     */
    QUIC_OBJ                *parent_obj;

    /* invariant: != NULL */
    QUIC_OBJ                *cached_event_leader;
    /* invariant: != NULL iff this is a port leader or subsidiary object */
    QUIC_OBJ                *cached_port_leader;

    /*
     * Points to the QUIC_ENGINE instance. Always equals
     * cached_event_leader->engine. The containing_obj APL object owns this
     * instance iff is_event_leader is set, otherwise it is an additional
     * reference cached for convenience. Unlike port this is never NULL because
     * a QUIC domain is always rooted in an event leader.
     */
    QUIC_ENGINE             *engine;

    /*
     * Points to the QUIC_PORT instance applicable to the containing_obj APL
     * object, or NULL if we are not at or below a port leader. Always equals
     * cached_port_leader->port. The containing_obj APL object owns this
     * instance iff is_port_leader is set, otherwise it is an additional
     * reference cached for convenience.
     */
    QUIC_PORT               *port;

    unsigned int            init_done       : 1;
    unsigned int            is_event_leader : 1;
    unsigned int            is_port_leader  : 1;
};

/*
 * Initialises a QUIC_OBJ structure with zero or more roles active. Returns 1
 * on success or 0 on failure.
 *
 * ctx: A SSL_CTX used to initialise the SSL base object structure.
 *
 * type: A SSL_TYPE_* value designating the SSL object type.
 *
 * parent_obj: NULL if this is the root APL object in a new hierarchy, or a
 * pointer to the parent APL object otherwise.
 *
 * engine: If non-NULL, this object becomes the Event Leader. parent_obj must be
 * NULL iff this is non-NULL as currently the Event Leader is always the root in
 * an APL object hierarchy. If NULL, the contextually applicable engine is
 * determined by using parent_obj and ancestors to find the Event Leader.
 *
 * port: If non-NULL, this object becomes a Port Leader. If NULL, the
 * contextually applicable port (if any) is determined by using parent_obj and
 * ancestors to find the Port Leader.
 */
int ossl_quic_obj_init(QUIC_OBJ *obj,
                       SSL_CTX *ctx,
                       int type,
                       SSL *parent_obj,
                       QUIC_ENGINE *engine,
                       QUIC_PORT *port);

/*
 * Returns a pointer to the handshake layer object which should be accessible on
 * obj for purposes of handshake API autoforwarding, if any.
 *
 * This returns NULL if a handshake layer SSL object is available but should not
 * be used for autoforwarding purposes, for example on a QSSO.
 */
SSL_CONNECTION *ossl_quic_obj_get0_handshake_layer(QUIC_OBJ *obj);

/*
 * Returns a pointer to the SSL base object structure. Returns NULL if obj is
 * NULL. If obj is non-NULL, it must be initialised.
 */
static ossl_inline ossl_unused SSL *
ossl_quic_obj_get0_ssl(QUIC_OBJ *obj)
{
    /*
     * ->ssl is guaranteed to have an offset of 0 but the NULL check here makes
     *  ubsan happy.
     */
    if (!ossl_assert(obj != NULL))
        return NULL;

    return &obj->ssl;
}

/*
 * Determines the applicable engine and return a pointer to it. Never returns
 * NULL.
 */
static ossl_inline ossl_unused QUIC_ENGINE *
ossl_quic_obj_get0_engine(const QUIC_OBJ *obj)
{
    assert(obj->init_done);
    assert(obj->engine != NULL);
    return obj->engine;
}

/* Determines the applicable port (if any) and returns a pointer to it. */
static ossl_inline ossl_unused QUIC_PORT *
ossl_quic_obj_get0_port(const QUIC_OBJ *obj)
{
    assert(obj->init_done);
    return obj->port;
}

/* Returns 1 iff this leader structure represents an event leader. */
static ossl_inline ossl_unused int
ossl_quic_obj_is_event_leader(const QUIC_OBJ *obj)
{
    return obj->is_event_leader;
}

/*
 * Similar to ossl_quic_obj_get0_engine, but only returns a non-NULL value if
 * the obj object itself is an event leader, rather than one of its ancestors.
 */
static ossl_inline ossl_unused QUIC_ENGINE *
ossl_quic_obj_get0_engine_local(const QUIC_OBJ *obj)
{
    return ossl_quic_obj_is_event_leader(obj)
        ? ossl_quic_obj_get0_engine(obj) : NULL;
}

/* Returns 1 iff this leader structure represents a port leader. */
static ossl_inline ossl_unused int
ossl_quic_obj_is_port_leader(const QUIC_OBJ *obj)
{
    return obj->is_port_leader;
}

/*
 * Similar to ossl_quic_obj_get0_port, but only returns a non-NULL value if
 * the obj object itself is a port leader, rather than one of its ancestors.
 */
static ossl_inline ossl_unused QUIC_PORT *
ossl_quic_obj_get0_port_local(const QUIC_OBJ *obj)
{
    return ossl_quic_obj_is_port_leader(obj)
        ? ossl_quic_obj_get0_port(obj) : NULL;
}

/*
 * Convenience Inlines
 * ===================
 */

/* Get a pointer to the QUIC domain mutex. Always returns non-NULL. */
static ossl_inline ossl_unused CRYPTO_MUTEX *
ossl_quic_obj_get0_mutex(const QUIC_OBJ *obj)
{
    return ossl_quic_engine_get0_mutex(ossl_quic_obj_get0_engine(obj));
}

/*
 * Get a reference to the reactor applicable to a leader. Always returns
 * non-NULL.
 */
static ossl_inline ossl_unused QUIC_REACTOR *
ossl_quic_obj_get0_reactor(const QUIC_OBJ *obj)
{
    return ossl_quic_engine_get0_reactor(ossl_quic_obj_get0_engine(obj));
}

/* Get a reference to the OSSL_LIB_CTX pointer applicable to a leader. */
static ossl_inline ossl_unused OSSL_LIB_CTX *
ossl_quic_obj_get0_libctx(const QUIC_OBJ *obj)
{
    return ossl_quic_engine_get0_libctx(ossl_quic_obj_get0_engine(obj));
}

/* Get a reference to the propq pointer applicable to a leader. */
static ossl_inline ossl_unused const char *
ossl_quic_obj_get0_propq(const QUIC_OBJ *obj)
{
    return ossl_quic_engine_get0_propq(ossl_quic_obj_get0_engine(obj));
}

/*
 * Returns the APL object pointer to the event leader in a hierarchy. Always
 * returns non-NULL.
 */
static ossl_inline ossl_unused SSL *
ossl_quic_obj_get0_event_leader(const QUIC_OBJ *obj)
{
    assert(obj->init_done);
    return obj->cached_event_leader != NULL
        ? &obj->cached_event_leader->ssl
        : NULL;
}

/*
 * Returns the APL object pointer to the port leader in a hierarchy (if any).
 * Always returns non-NULL.
 */
static ossl_inline ossl_unused SSL *
ossl_quic_obj_get0_port_leader(const QUIC_OBJ *obj)
{
    assert(obj->init_done);
    return obj->cached_port_leader != NULL
        ? &obj->cached_port_leader->ssl
        : NULL;
}

# endif
#endif