]> git.ipfire.org Git - thirdparty/openssl.git/blob - ssl/quic/quic_tserver.c
2a6049b1349e58a477397cd37568d91b3250bfee
[thirdparty/openssl.git] / ssl / quic / quic_tserver.c
1 /*
2 * Copyright 2022 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 "internal/quic_tserver.h"
11 #include "internal/quic_channel.h"
12 #include "internal/quic_statm.h"
13 #include "internal/common.h"
14
15 /*
16 * QUIC Test Server Module
17 * =======================
18 */
19 struct quic_tserver_st {
20 QUIC_TSERVER_ARGS args;
21
22 /*
23 * The QUIC channel providing the core QUIC connection implementation.
24 */
25 QUIC_CHANNEL *ch;
26
27 /* SSL_CTX for creating the underlying TLS connection */
28 SSL_CTX *ctx;
29
30 /* SSL for the underlying TLS connection */
31 SSL *tls;
32
33 /* Our single bidirectional application data stream. */
34 QUIC_STREAM *stream0;
35
36 /* The current peer L4 address. AF_UNSPEC if we do not have a peer yet. */
37 BIO_ADDR cur_peer_addr;
38
39 /* Are we connected to a peer? */
40 unsigned int connected : 1;
41 };
42
43 static int alpn_select_cb(SSL *ssl, const unsigned char **out,
44 unsigned char *outlen, const unsigned char *in,
45 unsigned int inlen, void *arg)
46 {
47 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
48
49 if (SSL_select_next_proto((unsigned char **)out, outlen, alpn, sizeof(alpn),
50 in, inlen) != OPENSSL_NPN_NEGOTIATED)
51 return SSL_TLSEXT_ERR_ALERT_FATAL;
52
53 return SSL_TLSEXT_ERR_OK;
54 }
55
56 QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
57 const char *certfile, const char *keyfile)
58 {
59 QUIC_TSERVER *srv = NULL;
60 QUIC_CHANNEL_ARGS ch_args = {0};
61
62 if (args->net_rbio == NULL || args->net_wbio == NULL)
63 goto err;
64
65 if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)
66 goto err;
67
68 srv->args = *args;
69
70 srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq, TLS_method());
71 if (srv->ctx == NULL)
72 goto err;
73
74 if (SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)
75 goto err;
76
77 if (SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
78 goto err;
79
80 SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);
81
82 srv->tls = SSL_new(srv->ctx);
83 if (srv->tls == NULL)
84 goto err;
85
86 ch_args.libctx = srv->args.libctx;
87 ch_args.propq = srv->args.propq;
88 ch_args.tls = srv->tls;
89 ch_args.is_server = 1;
90
91 if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL)
92 goto err;
93
94 if (!ossl_quic_channel_set_net_rbio(srv->ch, srv->args.net_rbio)
95 || !ossl_quic_channel_set_net_wbio(srv->ch, srv->args.net_wbio))
96 goto err;
97
98 srv->stream0 = ossl_quic_channel_get_stream_by_id(srv->ch, 0);
99 if (srv->stream0 == NULL)
100 goto err;
101
102 return srv;
103
104 err:
105 if (srv != NULL)
106 ossl_quic_channel_free(srv->ch);
107
108 OPENSSL_free(srv);
109 return NULL;
110 }
111
112 void ossl_quic_tserver_free(QUIC_TSERVER *srv)
113 {
114 if (srv == NULL)
115 return;
116
117 ossl_quic_channel_free(srv->ch);
118 BIO_free(srv->args.net_rbio);
119 BIO_free(srv->args.net_wbio);
120 SSL_free(srv->tls);
121 SSL_CTX_free(srv->ctx);
122 OPENSSL_free(srv);
123 }
124
125 /* Set mutator callbacks for test framework support */
126 int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER *srv,
127 ossl_mutate_packet_cb mutatecb,
128 ossl_finish_mutate_cb finishmutatecb,
129 void *mutatearg)
130 {
131 return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,
132 mutatearg);
133 }
134
135 int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,
136 ossl_statem_mutate_handshake_cb mutate_handshake_cb,
137 ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,
138 void *mutatearg)
139 {
140 return ossl_statem_set_mutator(ossl_quic_channel_get0_ssl(srv->ch),
141 mutate_handshake_cb,
142 finish_mutate_handshake_cb,
143 mutatearg);
144 }
145
146 int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
147 {
148 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));
149
150 if (ossl_quic_channel_is_active(srv->ch))
151 srv->connected = 1;
152
153 return 1;
154 }
155
156 int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
157 {
158 return ossl_quic_channel_is_active(srv->ch);
159 }
160
161 /* Returns 1 if the server is in any terminating or terminated state */
162 int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv,
163 QUIC_TERMINATE_CAUSE *cause)
164 {
165 return ossl_quic_channel_is_term_any(srv->ch, cause);
166 }
167
168 /* Returns 1 if the server is in a terminated state */
169 int ossl_quic_tserver_is_terminated(QUIC_TSERVER *srv,
170 QUIC_TERMINATE_CAUSE *cause)
171 {
172 return ossl_quic_channel_is_terminated(srv->ch, cause);
173 }
174
175 int ossl_quic_tserver_read(QUIC_TSERVER *srv,
176 unsigned char *buf,
177 size_t buf_len,
178 size_t *bytes_read)
179 {
180 int is_fin = 0;
181
182 if (!ossl_quic_channel_is_active(srv->ch))
183 return 0;
184
185 if (srv->stream0->recv_fin_retired)
186 return 0;
187
188 if (!ossl_quic_rstream_read(srv->stream0->rstream, buf, buf_len,
189 bytes_read, &is_fin))
190 return 0;
191
192 if (*bytes_read > 0) {
193 /*
194 * We have read at least one byte from the stream. Inform stream-level
195 * RXFC of the retirement of controlled bytes. Update the active stream
196 * status (the RXFC may now want to emit a frame granting more credit to
197 * the peer).
198 */
199 OSSL_RTT_INFO rtt_info;
200
201 ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);
202
203 if (!ossl_quic_rxfc_on_retire(&srv->stream0->rxfc, *bytes_read,
204 rtt_info.smoothed_rtt))
205 return 0;
206 }
207
208 if (is_fin)
209 srv->stream0->recv_fin_retired = 1;
210
211 if (*bytes_read > 0)
212 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
213 srv->stream0);
214
215 return 1;
216 }
217
218 int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv)
219 {
220 return srv->stream0->recv_fin_retired;
221 }
222
223 int ossl_quic_tserver_write(QUIC_TSERVER *srv,
224 const unsigned char *buf,
225 size_t buf_len,
226 size_t *bytes_written)
227 {
228 if (!ossl_quic_channel_is_active(srv->ch))
229 return 0;
230
231 if (!ossl_quic_sstream_append(srv->stream0->sstream,
232 buf, buf_len, bytes_written))
233 return 0;
234
235 if (*bytes_written > 0)
236 /*
237 * We have appended at least one byte to the stream. Potentially mark
238 * the stream as active, depending on FC.
239 */
240 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
241 srv->stream0);
242
243 /* Try and send. */
244 ossl_quic_tserver_tick(srv);
245 return 1;
246 }
247
248 int ossl_quic_tserver_conclude(QUIC_TSERVER *srv)
249 {
250 if (!ossl_quic_channel_is_active(srv->ch))
251 return 0;
252
253 if (!ossl_quic_sstream_get_final_size(srv->stream0->sstream, NULL)) {
254 ossl_quic_sstream_fin(srv->stream0->sstream);
255 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
256 srv->stream0);
257 }
258
259 ossl_quic_tserver_tick(srv);
260 return 1;
261 }