/src/openssl/ssl/quic/quic_obj.c
Line  | Count  | Source  | 
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  |  | #include "quic_obj_local.h"  | 
11  |  | #include "quic_local.h"  | 
12  |  | #include "internal/ssl_unwrap.h"  | 
13  |  |  | 
14  |  | static int obj_update_cache(QUIC_OBJ *obj);  | 
15  |  |  | 
16  |  | int ossl_quic_obj_init(QUIC_OBJ *obj,  | 
17  |  |                        SSL_CTX *ctx,  | 
18  |  |                        int type,  | 
19  |  |                        SSL *parent_obj,  | 
20  |  |                        QUIC_ENGINE *engine,  | 
21  |  |                        QUIC_PORT *port)  | 
22  | 0  | { | 
23  | 0  |     int is_event_leader = (engine != NULL);  | 
24  | 0  |     int is_port_leader  = (port != NULL);  | 
25  |  | 
  | 
26  | 0  |     if (!ossl_assert(obj != NULL && !obj->init_done && SSL_TYPE_IS_QUIC(type)  | 
27  | 0  |                      && (parent_obj == NULL || IS_QUIC(parent_obj))))  | 
28  | 0  |         return 0;  | 
29  |  |  | 
30  |  |     /* Event leader is always the root object. */  | 
31  | 0  |     if (!ossl_assert(!is_event_leader || parent_obj == NULL))  | 
32  | 0  |         return 0;  | 
33  |  |  | 
34  | 0  |     if (!ossl_ssl_init(&obj->ssl, ctx, ctx->method, type))  | 
35  | 0  |         goto err;  | 
36  |  |  | 
37  | 0  |     obj->domain_flags       = ctx->domain_flags;  | 
38  | 0  |     obj->parent_obj         = (QUIC_OBJ *)parent_obj;  | 
39  | 0  |     obj->is_event_leader    = is_event_leader;  | 
40  | 0  |     obj->is_port_leader     = is_port_leader;  | 
41  | 0  |     obj->engine             = engine;  | 
42  | 0  |     obj->port               = port;  | 
43  | 0  |     obj->req_blocking_mode  = QUIC_BLOCKING_MODE_INHERIT;  | 
44  | 0  |     if (!obj_update_cache(obj))  | 
45  | 0  |         goto err;  | 
46  |  |  | 
47  | 0  |     obj->init_done          = 1;  | 
48  | 0  |     return 1;  | 
49  |  |  | 
50  | 0  | err:  | 
51  | 0  |     obj->is_event_leader = 0;  | 
52  | 0  |     obj->is_port_leader  = 0;  | 
53  | 0  |     return 0;  | 
54  | 0  | }  | 
55  |  |  | 
56  |  | static int obj_update_cache(QUIC_OBJ *obj)  | 
57  | 0  | { | 
58  | 0  |     QUIC_OBJ *p;  | 
59  |  | 
  | 
60  | 0  |     for (p = obj; p != NULL && !p->is_event_leader;  | 
61  | 0  |          p = p->parent_obj)  | 
62  | 0  |         if (!ossl_assert(p == obj || p->init_done))  | 
63  | 0  |             return 0;  | 
64  |  |  | 
65  | 0  |     if (!ossl_assert(p != NULL))  | 
66  | 0  |         return 0;  | 
67  |  |  | 
68  |  |     /*  | 
69  |  |      * Offset of ->ssl is guaranteed to be 0 but the NULL check makes ubsan  | 
70  |  |      * happy.  | 
71  |  |      */  | 
72  | 0  |     obj->cached_event_leader    = p;  | 
73  | 0  |     obj->engine                 = p->engine;  | 
74  |  | 
  | 
75  | 0  |     for (p = obj; p != NULL && !p->is_port_leader;  | 
76  | 0  |          p = p->parent_obj);  | 
77  |  | 
  | 
78  | 0  |     obj->cached_port_leader     = p;  | 
79  | 0  |     obj->port                   = (p != NULL) ? p->port : NULL;  | 
80  | 0  |     return 1;  | 
81  | 0  | }  | 
82  |  |  | 
83  |  | SSL_CONNECTION *ossl_quic_obj_get0_handshake_layer(QUIC_OBJ *obj)  | 
84  | 0  | { | 
85  | 0  |     assert(obj != NULL && obj->init_done);  | 
86  |  | 
  | 
87  | 0  |     if (obj->ssl.type != SSL_TYPE_QUIC_CONNECTION)  | 
88  | 0  |         return NULL;  | 
89  |  |  | 
90  | 0  |     return SSL_CONNECTION_FROM_SSL_ONLY(((QUIC_CONNECTION *)obj)->tls);  | 
91  | 0  | }  | 
92  |  |  | 
93  |  | /* (Returns a cached result.) */  | 
94  |  | int ossl_quic_obj_can_support_blocking(const QUIC_OBJ *obj)  | 
95  | 0  | { | 
96  | 0  |     QUIC_REACTOR *rtor;  | 
97  |  | 
  | 
98  | 0  |     assert(obj != NULL);  | 
99  | 0  |     rtor = ossl_quic_obj_get0_reactor(obj);  | 
100  |  | 
  | 
101  | 0  |     if ((obj->domain_flags  | 
102  | 0  |             & (SSL_DOMAIN_FLAG_LEGACY_BLOCKING | SSL_DOMAIN_FLAG_BLOCKING)) == 0)  | 
103  | 0  |         return 0;  | 
104  |  |  | 
105  | 0  |     return ossl_quic_reactor_can_poll_r(rtor)  | 
106  | 0  |         || ossl_quic_reactor_can_poll_w(rtor);  | 
107  | 0  | }  | 
108  |  |  | 
109  |  | int ossl_quic_obj_desires_blocking(const QUIC_OBJ *obj)  | 
110  | 0  | { | 
111  | 0  |     unsigned int req_blocking_mode;  | 
112  |  | 
  | 
113  | 0  |     assert(obj != NULL);  | 
114  | 0  |     for (; (req_blocking_mode = obj->req_blocking_mode) == QUIC_BLOCKING_MODE_INHERIT  | 
115  | 0  |            && obj->parent_obj != NULL; obj = obj->parent_obj);  | 
116  |  | 
  | 
117  | 0  |     return req_blocking_mode != QUIC_BLOCKING_MODE_NONBLOCKING;  | 
118  | 0  | }  | 
119  |  |  | 
120  |  | int ossl_quic_obj_blocking(const QUIC_OBJ *obj)  | 
121  | 0  | { | 
122  | 0  |     assert(obj != NULL);  | 
123  |  | 
  | 
124  | 0  |     if (!ossl_quic_obj_desires_blocking(obj))  | 
125  | 0  |         return 0;  | 
126  |  |  | 
127  | 0  |     ossl_quic_engine_update_poll_descriptors(ossl_quic_obj_get0_engine(obj),  | 
128  | 0  |                                              /*force=*/0);  | 
129  | 0  |     return ossl_quic_obj_can_support_blocking(obj);  | 
130  | 0  | }  | 
131  |  |  | 
132  |  | void ossl_quic_obj_set_blocking_mode(QUIC_OBJ *obj, unsigned int mode)  | 
133  | 0  | { | 
134  | 0  |     assert(obj != NULL);  | 
135  |  | 
  | 
136  | 0  |     obj->req_blocking_mode = mode;  | 
137  | 0  | }  |