/src/openssl/ssl/quic/quic_obj.c
Line | Count | Source (jump to first uncovered line) |
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 | } |