VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.2/ssl/quic/quic_tserver.c

Last change on this file was 108206, checked in by vboxsync, 3 months ago

openssl-3.3.2: Exported all files to OSE and removed .scm-settings ​bugref:10757

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.2 KB
Line 
1/*
2 * Copyright 2022-2024 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/quic_port.h"
14#include "internal/quic_engine.h"
15#include "internal/common.h"
16#include "internal/time.h"
17#include "quic_local.h"
18
19/*
20 * QUIC Test Server Module
21 * =======================
22 */
23struct quic_tserver_st {
24 QUIC_TSERVER_ARGS args;
25
26 /* Dummy SSL object for this QUIC connection for use by msg_callback */
27 SSL *ssl;
28
29 /*
30 * The QUIC engine, port and channel providing the core QUIC connection
31 * implementation.
32 */
33 QUIC_ENGINE *engine;
34 QUIC_PORT *port;
35 QUIC_CHANNEL *ch;
36
37 /* The mutex we give to the QUIC channel. */
38 CRYPTO_MUTEX *mutex;
39
40 /* SSL_CTX for creating the underlying TLS connection */
41 SSL_CTX *ctx;
42
43 /* SSL for the underlying TLS connection */
44 SSL *tls;
45
46 /* The current peer L4 address. AF_UNSPEC if we do not have a peer yet. */
47 BIO_ADDR cur_peer_addr;
48
49 /* Are we connected to a peer? */
50 unsigned int connected : 1;
51};
52
53static int alpn_select_cb(SSL *ssl, const unsigned char **out,
54 unsigned char *outlen, const unsigned char *in,
55 unsigned int inlen, void *arg)
56{
57 QUIC_TSERVER *srv = arg;
58 static const unsigned char alpndeflt[] = {
59 8, 'o', 's', 's', 'l', 't', 'e', 's', 't'
60 };
61 const unsigned char *alpn;
62 size_t alpnlen;
63
64 if (srv->args.alpn == NULL) {
65 alpn = alpndeflt;
66 alpnlen = sizeof(alpndeflt);
67 } else {
68 alpn = srv->args.alpn;
69 alpnlen = srv->args.alpnlen;
70 }
71
72 if (SSL_select_next_proto((unsigned char **)out, outlen, alpn, alpnlen,
73 in, inlen) != OPENSSL_NPN_NEGOTIATED)
74 return SSL_TLSEXT_ERR_ALERT_FATAL;
75
76 return SSL_TLSEXT_ERR_OK;
77}
78
79QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
80 const char *certfile, const char *keyfile)
81{
82 QUIC_TSERVER *srv = NULL;
83 QUIC_ENGINE_ARGS engine_args = {0};
84 QUIC_PORT_ARGS port_args = {0};
85 QUIC_CONNECTION *qc = NULL;
86
87 if (args->net_rbio == NULL || args->net_wbio == NULL)
88 goto err;
89
90 if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)
91 goto err;
92
93 srv->args = *args;
94
95#if defined(OPENSSL_THREADS)
96 if ((srv->mutex = ossl_crypto_mutex_new()) == NULL)
97 goto err;
98#endif
99
100 if (args->ctx != NULL)
101 srv->ctx = args->ctx;
102 else
103 srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq,
104 TLS_method());
105 if (srv->ctx == NULL)
106 goto err;
107
108 if (certfile != NULL
109 && SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)
110 goto err;
111
112 if (keyfile != NULL
113 && SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
114 goto err;
115
116 SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);
117
118 srv->tls = SSL_new(srv->ctx);
119 if (srv->tls == NULL)
120 goto err;
121
122 engine_args.libctx = srv->args.libctx;
123 engine_args.propq = srv->args.propq;
124 engine_args.mutex = srv->mutex;
125 engine_args.now_cb = srv->args.now_cb;
126 engine_args.now_cb_arg = srv->args.now_cb_arg;
127
128 if ((srv->engine = ossl_quic_engine_new(&engine_args)) == NULL)
129 goto err;
130
131 port_args.channel_ctx = srv->ctx;
132 port_args.is_multi_conn = 1;
133
134 if ((srv->port = ossl_quic_engine_create_port(srv->engine, &port_args)) == NULL)
135 goto err;
136
137 if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL)
138 goto err;
139
140 if (!ossl_quic_port_set_net_rbio(srv->port, srv->args.net_rbio)
141 || !ossl_quic_port_set_net_wbio(srv->port, srv->args.net_wbio))
142 goto err;
143
144 qc = OPENSSL_zalloc(sizeof(*qc));
145 if (qc == NULL)
146 goto err;
147 srv->ssl = (SSL *)qc;
148 qc->ch = srv->ch;
149 srv->ssl->type = SSL_TYPE_QUIC_CONNECTION;
150
151 return srv;
152
153err:
154 if (srv != NULL) {
155 if (args->ctx == NULL)
156 SSL_CTX_free(srv->ctx);
157 SSL_free(srv->tls);
158 ossl_quic_channel_free(srv->ch);
159 ossl_quic_port_free(srv->port);
160 ossl_quic_engine_free(srv->engine);
161#if defined(OPENSSL_THREADS)
162 ossl_crypto_mutex_free(&srv->mutex);
163#endif
164 OPENSSL_free(qc);
165 }
166
167 OPENSSL_free(srv);
168 return NULL;
169}
170
171void ossl_quic_tserver_free(QUIC_TSERVER *srv)
172{
173 if (srv == NULL)
174 return;
175
176 SSL_free(srv->tls);
177 ossl_quic_channel_free(srv->ch);
178 ossl_quic_port_free(srv->port);
179 ossl_quic_engine_free(srv->engine);
180 BIO_free_all(srv->args.net_rbio);
181 BIO_free_all(srv->args.net_wbio);
182 OPENSSL_free(srv->ssl);
183 SSL_CTX_free(srv->ctx);
184#if defined(OPENSSL_THREADS)
185 ossl_crypto_mutex_free(&srv->mutex);
186#endif
187 OPENSSL_free(srv);
188}
189
190/* Set mutator callbacks for test framework support */
191int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER *srv,
192 ossl_mutate_packet_cb mutatecb,
193 ossl_finish_mutate_cb finishmutatecb,
194 void *mutatearg)
195{
196 return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,
197 mutatearg);
198}
199
200int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER *srv,
201 ossl_statem_mutate_handshake_cb mutate_handshake_cb,
202 ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb,
203 void *mutatearg)
204{
205 return ossl_statem_set_mutator(ossl_quic_channel_get0_ssl(srv->ch),
206 mutate_handshake_cb,
207 finish_mutate_handshake_cb,
208 mutatearg);
209}
210
211int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
212{
213 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
214
215 if (ossl_quic_channel_is_active(srv->ch))
216 srv->connected = 1;
217
218 return 1;
219}
220
221int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
222{
223 return ossl_quic_channel_is_active(srv->ch);
224}
225
226/* Returns 1 if the server is in any terminating or terminated state */
227int ossl_quic_tserver_is_term_any(const QUIC_TSERVER *srv)
228{
229 return ossl_quic_channel_is_term_any(srv->ch);
230}
231
232const QUIC_TERMINATE_CAUSE *
233ossl_quic_tserver_get_terminate_cause(const QUIC_TSERVER *srv)
234{
235 return ossl_quic_channel_get_terminate_cause(srv->ch);
236}
237
238/* Returns 1 if the server is in a terminated state */
239int ossl_quic_tserver_is_terminated(const QUIC_TSERVER *srv)
240{
241 return ossl_quic_channel_is_terminated(srv->ch);
242}
243
244int ossl_quic_tserver_is_handshake_confirmed(const QUIC_TSERVER *srv)
245{
246 return ossl_quic_channel_is_handshake_confirmed(srv->ch);
247}
248
249int ossl_quic_tserver_read(QUIC_TSERVER *srv,
250 uint64_t stream_id,
251 unsigned char *buf,
252 size_t buf_len,
253 size_t *bytes_read)
254{
255 int is_fin = 0;
256 QUIC_STREAM *qs;
257
258 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
259 stream_id);
260 if (qs == NULL) {
261 int is_client_init
262 = ((stream_id & QUIC_STREAM_INITIATOR_MASK)
263 == QUIC_STREAM_INITIATOR_CLIENT);
264
265 /*
266 * A client-initiated stream might spontaneously come into existence, so
267 * allow trying to read on a client-initiated stream before it exists,
268 * assuming the connection is still active.
269 * Otherwise, fail.
270 */
271 if (!is_client_init || !ossl_quic_channel_is_active(srv->ch))
272 return 0;
273
274 *bytes_read = 0;
275 return 1;
276 }
277
278 if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ
279 || !ossl_quic_stream_has_recv_buffer(qs))
280 return 0;
281
282 if (!ossl_quic_rstream_read(qs->rstream, buf, buf_len,
283 bytes_read, &is_fin))
284 return 0;
285
286 if (*bytes_read > 0) {
287 /*
288 * We have read at least one byte from the stream. Inform stream-level
289 * RXFC of the retirement of controlled bytes. Update the active stream
290 * status (the RXFC may now want to emit a frame granting more credit to
291 * the peer).
292 */
293 OSSL_RTT_INFO rtt_info;
294
295 ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);
296
297 if (!ossl_quic_rxfc_on_retire(&qs->rxfc, *bytes_read,
298 rtt_info.smoothed_rtt))
299 return 0;
300 }
301
302 if (is_fin)
303 ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),
304 qs);
305
306 if (*bytes_read > 0)
307 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);
308
309 return 1;
310}
311
312int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv, uint64_t stream_id)
313{
314 QUIC_STREAM *qs;
315 unsigned char buf[1];
316 size_t bytes_read = 0;
317 int is_fin = 0;
318
319 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
320 stream_id);
321
322 if (qs == NULL)
323 return 0;
324
325 if (qs->recv_state == QUIC_RSTREAM_STATE_DATA_READ)
326 return 1;
327
328 if (!ossl_quic_stream_has_recv_buffer(qs))
329 return 0;
330
331 /*
332 * If we do not have the DATA_READ, it is possible we should still return 1
333 * if there is a lone FIN (but no more data) remaining to be retired from
334 * the RSTREAM, for example because ossl_quic_tserver_read() has not been
335 * called since the FIN was received.
336 */
337 if (!ossl_quic_rstream_peek(qs->rstream, buf, sizeof(buf),
338 &bytes_read, &is_fin))
339 return 0;
340
341 if (is_fin && bytes_read == 0) {
342 /* If we have a FIN awaiting retirement and no data before it... */
343 /* Let RSTREAM know we've consumed this FIN. */
344 if (!ossl_quic_rstream_read(qs->rstream, buf, sizeof(buf),
345 &bytes_read, &is_fin))
346 return 0;
347
348 assert(is_fin && bytes_read == 0);
349 assert(qs->recv_state == QUIC_RSTREAM_STATE_DATA_RECVD);
350
351 ossl_quic_stream_map_notify_totally_read(ossl_quic_channel_get_qsm(srv->ch),
352 qs);
353 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);
354 return 1;
355 }
356
357 return 0;
358}
359
360int ossl_quic_tserver_write(QUIC_TSERVER *srv,
361 uint64_t stream_id,
362 const unsigned char *buf,
363 size_t buf_len,
364 size_t *bytes_written)
365{
366 QUIC_STREAM *qs;
367
368 if (!ossl_quic_channel_is_active(srv->ch))
369 return 0;
370
371 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
372 stream_id);
373 if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))
374 return 0;
375
376 if (!ossl_quic_sstream_append(qs->sstream,
377 buf, buf_len, bytes_written))
378 return 0;
379
380 if (*bytes_written > 0)
381 /*
382 * We have appended at least one byte to the stream. Potentially mark
383 * the stream as active, depending on FC.
384 */
385 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);
386
387 /* Try and send. */
388 ossl_quic_tserver_tick(srv);
389 return 1;
390}
391
392int ossl_quic_tserver_conclude(QUIC_TSERVER *srv, uint64_t stream_id)
393{
394 QUIC_STREAM *qs;
395
396 if (!ossl_quic_channel_is_active(srv->ch))
397 return 0;
398
399 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
400 stream_id);
401 if (qs == NULL || !ossl_quic_stream_has_send_buffer(qs))
402 return 0;
403
404 if (!ossl_quic_sstream_get_final_size(qs->sstream, NULL)) {
405 ossl_quic_sstream_fin(qs->sstream);
406 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch), qs);
407 }
408
409 ossl_quic_tserver_tick(srv);
410 return 1;
411}
412
413int ossl_quic_tserver_stream_new(QUIC_TSERVER *srv,
414 int is_uni,
415 uint64_t *stream_id)
416{
417 QUIC_STREAM *qs;
418
419 if (!ossl_quic_channel_is_active(srv->ch))
420 return 0;
421
422 if ((qs = ossl_quic_channel_new_stream_local(srv->ch, is_uni)) == NULL)
423 return 0;
424
425 *stream_id = qs->id;
426 return 1;
427}
428
429BIO *ossl_quic_tserver_get0_rbio(QUIC_TSERVER *srv)
430{
431 return srv->args.net_rbio;
432}
433
434SSL_CTX *ossl_quic_tserver_get0_ssl_ctx(QUIC_TSERVER *srv)
435{
436 return srv->ctx;
437}
438
439int ossl_quic_tserver_stream_has_peer_stop_sending(QUIC_TSERVER *srv,
440 uint64_t stream_id,
441 uint64_t *app_error_code)
442{
443 QUIC_STREAM *qs;
444
445 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
446 stream_id);
447 if (qs == NULL)
448 return 0;
449
450 if (qs->peer_stop_sending && app_error_code != NULL)
451 *app_error_code = qs->peer_stop_sending_aec;
452
453 return qs->peer_stop_sending;
454}
455
456int ossl_quic_tserver_stream_has_peer_reset_stream(QUIC_TSERVER *srv,
457 uint64_t stream_id,
458 uint64_t *app_error_code)
459{
460 QUIC_STREAM *qs;
461
462 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
463 stream_id);
464 if (qs == NULL)
465 return 0;
466
467 if (ossl_quic_stream_recv_is_reset(qs) && app_error_code != NULL)
468 *app_error_code = qs->peer_reset_stream_aec;
469
470 return ossl_quic_stream_recv_is_reset(qs);
471}
472
473int ossl_quic_tserver_set_new_local_cid(QUIC_TSERVER *srv,
474 const QUIC_CONN_ID *conn_id)
475{
476 /* Replace existing local connection ID in the QUIC_CHANNEL */
477 return ossl_quic_channel_replace_local_cid(srv->ch, conn_id);
478}
479
480uint64_t ossl_quic_tserver_pop_incoming_stream(QUIC_TSERVER *srv)
481{
482 QUIC_STREAM_MAP *qsm = ossl_quic_channel_get_qsm(srv->ch);
483 QUIC_STREAM *qs = ossl_quic_stream_map_peek_accept_queue(qsm);
484
485 if (qs == NULL)
486 return UINT64_MAX;
487
488 ossl_quic_stream_map_remove_from_accept_queue(qsm, qs, ossl_time_zero());
489
490 return qs->id;
491}
492
493int ossl_quic_tserver_is_stream_totally_acked(QUIC_TSERVER *srv,
494 uint64_t stream_id)
495{
496 QUIC_STREAM *qs;
497
498 qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(srv->ch),
499 stream_id);
500 if (qs == NULL)
501 return 1;
502
503 return ossl_quic_sstream_is_totally_acked(qs->sstream);
504}
505
506int ossl_quic_tserver_get_net_read_desired(QUIC_TSERVER *srv)
507{
508 return ossl_quic_reactor_net_read_desired(
509 ossl_quic_channel_get_reactor(srv->ch));
510}
511
512int ossl_quic_tserver_get_net_write_desired(QUIC_TSERVER *srv)
513{
514 return ossl_quic_reactor_net_write_desired(
515 ossl_quic_channel_get_reactor(srv->ch));
516}
517
518OSSL_TIME ossl_quic_tserver_get_deadline(QUIC_TSERVER *srv)
519{
520 return ossl_quic_reactor_get_tick_deadline(
521 ossl_quic_channel_get_reactor(srv->ch));
522}
523
524int ossl_quic_tserver_shutdown(QUIC_TSERVER *srv, uint64_t app_error_code)
525{
526 ossl_quic_channel_local_close(srv->ch, app_error_code, NULL);
527
528 /* TODO(QUIC SERVER): !SSL_SHUTDOWN_FLAG_NO_STREAM_FLUSH */
529
530 if (ossl_quic_channel_is_terminated(srv->ch))
531 return 1;
532
533 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
534
535 return ossl_quic_channel_is_terminated(srv->ch);
536}
537
538int ossl_quic_tserver_ping(QUIC_TSERVER *srv)
539{
540 if (ossl_quic_channel_is_terminated(srv->ch))
541 return 0;
542
543 if (!ossl_quic_channel_ping(srv->ch))
544 return 0;
545
546 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch), 0);
547 return 1;
548}
549
550QUIC_CHANNEL *ossl_quic_tserver_get_channel(QUIC_TSERVER *srv)
551{
552 return srv->ch;
553}
554
555void ossl_quic_tserver_set_msg_callback(QUIC_TSERVER *srv,
556 void (*f)(int write_p, int version,
557 int content_type,
558 const void *buf, size_t len,
559 SSL *ssl, void *arg),
560 void *arg)
561{
562 ossl_quic_channel_set_msg_callback(srv->ch, f, srv->ssl);
563 ossl_quic_channel_set_msg_callback_arg(srv->ch, arg);
564 SSL_set_msg_callback(srv->tls, f);
565 SSL_set_msg_callback_arg(srv->tls, arg);
566}
567
568int ossl_quic_tserver_new_ticket(QUIC_TSERVER *srv)
569{
570 return SSL_new_session_ticket(srv->tls);
571}
572
573int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv,
574 uint32_t max_early_data)
575{
576 return SSL_set_max_early_data(srv->tls, max_early_data);
577}
578
579void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv,
580 SSL_psk_find_session_cb_func cb)
581{
582 SSL_set_psk_find_session_callback(srv->tls, cb);
583}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette