forked from openssl/openssl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquic_channel.c
3704 lines (3111 loc) · 126 KB
/
quic_channel.c
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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright 2022-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
*/
#include <openssl/rand.h>
#include <openssl/err.h>
#include "internal/quic_channel.h"
#include "internal/quic_error.h"
#include "internal/quic_rx_depack.h"
#include "internal/quic_lcidm.h"
#include "internal/quic_srtm.h"
#include "internal/qlog_event_helpers.h"
#include "../ssl_local.h"
#include "quic_channel_local.h"
#include "quic_port_local.h"
#include "quic_engine_local.h"
/*
* NOTE: While this channel implementation currently has basic server support,
* this functionality has been implemented for internal testing purposes and is
* not suitable for network use. In particular, it does not implement address
* validation, anti-amplification or retry logic.
*
* TODO(QUIC SERVER): Implement address validation and anti-amplification
* TODO(QUIC SERVER): Implement retry logic
*/
#define INIT_CRYPTO_RECV_BUF_LEN 16384
#define INIT_CRYPTO_SEND_BUF_LEN 16384
#define INIT_APP_BUF_LEN 8192
/*
* Interval before we force a PING to ensure NATs don't timeout. This is based
* on the lowest commonly seen value of 30 seconds as cited in RFC 9000 s.
* 10.1.2.
*/
#define MAX_NAT_INTERVAL (ossl_ms2time(25000))
/*
* Our maximum ACK delay on the TX side. This is up to us to choose. Note that
* this could differ from QUIC_DEFAULT_MAX_DELAY in future as that is a protocol
* value which determines the value of the maximum ACK delay if the
* max_ack_delay transport parameter is not set.
*/
#define DEFAULT_MAX_ACK_DELAY QUIC_DEFAULT_MAX_ACK_DELAY
DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL);
static void ch_save_err_state(QUIC_CHANNEL *ch);
static int ch_rx(QUIC_CHANNEL *ch, int channel_only);
static int ch_tx(QUIC_CHANNEL *ch);
static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only);
static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only);
static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch);
static int ch_retry(QUIC_CHANNEL *ch,
const unsigned char *retry_token,
size_t retry_token_len,
const QUIC_CONN_ID *retry_scid);
static void ch_cleanup(QUIC_CHANNEL *ch);
static int ch_generate_transport_params(QUIC_CHANNEL *ch);
static int ch_on_transport_params(const unsigned char *params,
size_t params_len,
void *arg);
static int ch_on_handshake_alert(void *arg, unsigned char alert_code);
static int ch_on_handshake_complete(void *arg);
static int ch_on_handshake_yield_secret(uint32_t enc_level, int direction,
uint32_t suite_id, EVP_MD *md,
const unsigned char *secret,
size_t secret_len,
void *arg);
static int ch_on_crypto_recv_record(const unsigned char **buf,
size_t *bytes_read, void *arg);
static int ch_on_crypto_release_record(size_t bytes_read, void *arg);
static int crypto_ensure_empty(QUIC_RSTREAM *rstream);
static int ch_on_crypto_send(const unsigned char *buf, size_t buf_len,
size_t *consumed, void *arg);
static OSSL_TIME get_time(void *arg);
static uint64_t get_stream_limit(int uni, void *arg);
static int rx_late_validate(QUIC_PN pn, int pn_space, void *arg);
static void rxku_detected(QUIC_PN pn, void *arg);
static int ch_retry(QUIC_CHANNEL *ch,
const unsigned char *retry_token,
size_t retry_token_len,
const QUIC_CONN_ID *retry_scid);
static void ch_update_idle(QUIC_CHANNEL *ch);
static int ch_discard_el(QUIC_CHANNEL *ch,
uint32_t enc_level);
static void ch_on_idle_timeout(QUIC_CHANNEL *ch);
static void ch_update_idle(QUIC_CHANNEL *ch);
static void ch_update_ping_deadline(QUIC_CHANNEL *ch);
static void ch_on_terminating_timeout(QUIC_CHANNEL *ch);
static void ch_start_terminating(QUIC_CHANNEL *ch,
const QUIC_TERMINATE_CAUSE *tcause,
int force_immediate);
static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,
void *arg);
static void ch_rx_handle_version_neg(QUIC_CHANNEL *ch, OSSL_QRX_PKT *pkt);
static void ch_raise_version_neg_failure(QUIC_CHANNEL *ch);
static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state);
DEFINE_LHASH_OF_EX(QUIC_SRT_ELEM);
QUIC_NEEDS_LOCK
static QLOG *ch_get_qlog(QUIC_CHANNEL *ch)
{
#ifndef OPENSSL_NO_QLOG
QLOG_TRACE_INFO qti = {0};
if (ch->qlog != NULL)
return ch->qlog;
if (!ch->use_qlog)
return NULL;
if (ch->is_server && ch->init_dcid.id_len == 0)
return NULL;
qti.odcid = ch->init_dcid;
qti.title = ch->qlog_title;
qti.description = NULL;
qti.group_id = NULL;
qti.is_server = ch->is_server;
qti.now_cb = get_time;
qti.now_cb_arg = ch;
if ((ch->qlog = ossl_qlog_new_from_env(&qti)) == NULL) {
ch->use_qlog = 0; /* don't try again */
return NULL;
}
return ch->qlog;
#else
return NULL;
#endif
}
QUIC_NEEDS_LOCK
static QLOG *ch_get_qlog_cb(void *arg)
{
QUIC_CHANNEL *ch = arg;
return ch_get_qlog(ch);
}
/*
* QUIC Channel Initialization and Teardown
* ========================================
*/
#define DEFAULT_INIT_CONN_RXFC_WND (768 * 1024)
#define DEFAULT_CONN_RXFC_MAX_WND_MUL 20
#define DEFAULT_INIT_STREAM_RXFC_WND (512 * 1024)
#define DEFAULT_STREAM_RXFC_MAX_WND_MUL 12
#define DEFAULT_INIT_CONN_MAX_STREAMS 100
static int ch_init(QUIC_CHANNEL *ch)
{
OSSL_QUIC_TX_PACKETISER_ARGS txp_args = {0};
OSSL_QTX_ARGS qtx_args = {0};
OSSL_QRX_ARGS qrx_args = {0};
QUIC_TLS_ARGS tls_args = {0};
uint32_t pn_space;
size_t rx_short_dcid_len;
size_t tx_init_dcid_len;
if (ch->port == NULL || ch->lcidm == NULL || ch->srtm == NULL)
goto err;
rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port);
tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port);
/* For clients, generate our initial DCID. */
if (!ch->is_server
&& !ossl_quic_gen_rand_conn_id(ch->port->engine->libctx, tx_init_dcid_len,
&ch->init_dcid))
goto err;
/* We plug in a network write BIO to the QTX later when we get one. */
qtx_args.libctx = ch->port->engine->libctx;
qtx_args.get_qlog_cb = ch_get_qlog_cb;
qtx_args.get_qlog_cb_arg = ch;
qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN;
ch->rx_max_udp_payload_size = qtx_args.mdpl;
ch->ping_deadline = ossl_time_infinite();
ch->qtx = ossl_qtx_new(&qtx_args);
if (ch->qtx == NULL)
goto err;
ch->txpim = ossl_quic_txpim_new();
if (ch->txpim == NULL)
goto err;
ch->cfq = ossl_quic_cfq_new();
if (ch->cfq == NULL)
goto err;
if (!ossl_quic_txfc_init(&ch->conn_txfc, NULL))
goto err;
/*
* Note: The TP we transmit governs what the peer can transmit and thus
* applies to the RXFC.
*/
ch->tx_init_max_stream_data_bidi_local = DEFAULT_INIT_STREAM_RXFC_WND;
ch->tx_init_max_stream_data_bidi_remote = DEFAULT_INIT_STREAM_RXFC_WND;
ch->tx_init_max_stream_data_uni = DEFAULT_INIT_STREAM_RXFC_WND;
if (!ossl_quic_rxfc_init(&ch->conn_rxfc, NULL,
DEFAULT_INIT_CONN_RXFC_WND,
DEFAULT_CONN_RXFC_MAX_WND_MUL *
DEFAULT_INIT_CONN_RXFC_WND,
get_time, ch))
goto err;
for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space)
if (!ossl_quic_rxfc_init_standalone(&ch->crypto_rxfc[pn_space],
INIT_CRYPTO_RECV_BUF_LEN,
get_time, ch))
goto err;
if (!ossl_quic_rxfc_init_standalone(&ch->max_streams_bidi_rxfc,
DEFAULT_INIT_CONN_MAX_STREAMS,
get_time, ch))
goto err;
if (!ossl_quic_rxfc_init_standalone(&ch->max_streams_uni_rxfc,
DEFAULT_INIT_CONN_MAX_STREAMS,
get_time, ch))
goto err;
if (!ossl_statm_init(&ch->statm))
goto err;
ch->have_statm = 1;
ch->cc_method = &ossl_cc_newreno_method;
if ((ch->cc_data = ch->cc_method->new(get_time, ch)) == NULL)
goto err;
if ((ch->ackm = ossl_ackm_new(get_time, ch, &ch->statm,
ch->cc_method, ch->cc_data)) == NULL)
goto err;
if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch,
&ch->max_streams_bidi_rxfc,
&ch->max_streams_uni_rxfc,
ch->is_server))
goto err;
ch->have_qsm = 1;
if (!ch->is_server
&& !ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &txp_args.cur_scid))
goto err;
/* We use a zero-length SCID. */
txp_args.cur_dcid = ch->init_dcid;
txp_args.ack_delay_exponent = 3;
txp_args.qtx = ch->qtx;
txp_args.txpim = ch->txpim;
txp_args.cfq = ch->cfq;
txp_args.ackm = ch->ackm;
txp_args.qsm = &ch->qsm;
txp_args.conn_txfc = &ch->conn_txfc;
txp_args.conn_rxfc = &ch->conn_rxfc;
txp_args.max_streams_bidi_rxfc = &ch->max_streams_bidi_rxfc;
txp_args.max_streams_uni_rxfc = &ch->max_streams_uni_rxfc;
txp_args.cc_method = ch->cc_method;
txp_args.cc_data = ch->cc_data;
txp_args.now = get_time;
txp_args.now_arg = ch;
txp_args.get_qlog_cb = ch_get_qlog_cb;
txp_args.get_qlog_cb_arg = ch;
for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {
ch->crypto_send[pn_space] = ossl_quic_sstream_new(INIT_CRYPTO_SEND_BUF_LEN);
if (ch->crypto_send[pn_space] == NULL)
goto err;
txp_args.crypto[pn_space] = ch->crypto_send[pn_space];
}
ch->txp = ossl_quic_tx_packetiser_new(&txp_args);
if (ch->txp == NULL)
goto err;
ossl_quic_tx_packetiser_set_ack_tx_cb(ch->txp, ch_on_txp_ack_tx, ch);
qrx_args.libctx = ch->port->engine->libctx;
qrx_args.demux = ch->port->demux;
qrx_args.short_conn_id_len = rx_short_dcid_len;
qrx_args.max_deferred = 32;
if ((ch->qrx = ossl_qrx_new(&qrx_args)) == NULL)
goto err;
if (!ossl_qrx_set_late_validation_cb(ch->qrx,
rx_late_validate,
ch))
goto err;
if (!ossl_qrx_set_key_update_cb(ch->qrx,
rxku_detected,
ch))
goto err;
for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {
ch->crypto_recv[pn_space] = ossl_quic_rstream_new(NULL, NULL, 0);
if (ch->crypto_recv[pn_space] == NULL)
goto err;
}
/* Plug in the TLS handshake layer. */
tls_args.s = ch->tls;
tls_args.crypto_send_cb = ch_on_crypto_send;
tls_args.crypto_send_cb_arg = ch;
tls_args.crypto_recv_rcd_cb = ch_on_crypto_recv_record;
tls_args.crypto_recv_rcd_cb_arg = ch;
tls_args.crypto_release_rcd_cb = ch_on_crypto_release_record;
tls_args.crypto_release_rcd_cb_arg = ch;
tls_args.yield_secret_cb = ch_on_handshake_yield_secret;
tls_args.yield_secret_cb_arg = ch;
tls_args.got_transport_params_cb = ch_on_transport_params;
tls_args.got_transport_params_cb_arg= ch;
tls_args.handshake_complete_cb = ch_on_handshake_complete;
tls_args.handshake_complete_cb_arg = ch;
tls_args.alert_cb = ch_on_handshake_alert;
tls_args.alert_cb_arg = ch;
tls_args.is_server = ch->is_server;
if ((ch->qtls = ossl_quic_tls_new(&tls_args)) == NULL)
goto err;
ch->tx_max_ack_delay = DEFAULT_MAX_ACK_DELAY;
ch->rx_max_ack_delay = QUIC_DEFAULT_MAX_ACK_DELAY;
ch->rx_ack_delay_exp = QUIC_DEFAULT_ACK_DELAY_EXP;
ch->rx_active_conn_id_limit = QUIC_MIN_ACTIVE_CONN_ID_LIMIT;
ch->tx_enc_level = QUIC_ENC_LEVEL_INITIAL;
ch->rx_enc_level = QUIC_ENC_LEVEL_INITIAL;
ch->txku_threshold_override = UINT64_MAX;
ch->max_idle_timeout_local_req = QUIC_DEFAULT_IDLE_TIMEOUT;
ch->max_idle_timeout_remote_req = 0;
ch->max_idle_timeout = ch->max_idle_timeout_local_req;
ossl_ackm_set_tx_max_ack_delay(ch->ackm, ossl_ms2time(ch->tx_max_ack_delay));
ossl_ackm_set_rx_max_ack_delay(ch->ackm, ossl_ms2time(ch->rx_max_ack_delay));
ch_update_idle(ch);
ossl_list_ch_insert_tail(&ch->port->channel_list, ch);
ch->on_port_list = 1;
return 1;
err:
ch_cleanup(ch);
return 0;
}
static void ch_cleanup(QUIC_CHANNEL *ch)
{
uint32_t pn_space;
if (ch->ackm != NULL)
for (pn_space = QUIC_PN_SPACE_INITIAL;
pn_space < QUIC_PN_SPACE_NUM;
++pn_space)
ossl_ackm_on_pkt_space_discarded(ch->ackm, pn_space);
ossl_quic_lcidm_cull(ch->lcidm, ch);
ossl_quic_srtm_cull(ch->srtm, ch);
ossl_quic_tx_packetiser_free(ch->txp);
ossl_quic_txpim_free(ch->txpim);
ossl_quic_cfq_free(ch->cfq);
ossl_qtx_free(ch->qtx);
if (ch->cc_data != NULL)
ch->cc_method->free(ch->cc_data);
if (ch->have_statm)
ossl_statm_destroy(&ch->statm);
ossl_ackm_free(ch->ackm);
if (ch->have_qsm)
ossl_quic_stream_map_cleanup(&ch->qsm);
for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) {
ossl_quic_sstream_free(ch->crypto_send[pn_space]);
ossl_quic_rstream_free(ch->crypto_recv[pn_space]);
}
ossl_qrx_pkt_release(ch->qrx_pkt);
ch->qrx_pkt = NULL;
ossl_quic_tls_free(ch->qtls);
ossl_qrx_free(ch->qrx);
OPENSSL_free(ch->local_transport_params);
OPENSSL_free((char *)ch->terminate_cause.reason);
OSSL_ERR_STATE_free(ch->err_state);
OPENSSL_free(ch->ack_range_scratch);
if (ch->on_port_list) {
ossl_list_ch_remove(&ch->port->channel_list, ch);
ch->on_port_list = 0;
}
#ifndef OPENSSL_NO_QLOG
if (ch->qlog != NULL)
ossl_qlog_flush(ch->qlog); /* best effort */
OPENSSL_free(ch->qlog_title);
ossl_qlog_free(ch->qlog);
#endif
}
QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args)
{
QUIC_CHANNEL *ch = NULL;
if ((ch = OPENSSL_zalloc(sizeof(*ch))) == NULL)
return NULL;
ch->port = args->port;
ch->is_server = args->is_server;
ch->tls = args->tls;
ch->lcidm = args->lcidm;
ch->srtm = args->srtm;
#ifndef OPENSSL_NO_QLOG
ch->use_qlog = args->use_qlog;
if (ch->use_qlog && args->qlog_title != NULL) {
if ((ch->qlog_title = OPENSSL_strdup(args->qlog_title)) == NULL) {
OPENSSL_free(ch);
return NULL;
}
}
#endif
if (!ch_init(ch)) {
OPENSSL_free(ch);
return NULL;
}
return ch;
}
void ossl_quic_channel_free(QUIC_CHANNEL *ch)
{
if (ch == NULL)
return;
ch_cleanup(ch);
OPENSSL_free(ch);
}
/* Set mutator callbacks for test framework support */
int ossl_quic_channel_set_mutator(QUIC_CHANNEL *ch,
ossl_mutate_packet_cb mutatecb,
ossl_finish_mutate_cb finishmutatecb,
void *mutatearg)
{
if (ch->qtx == NULL)
return 0;
ossl_qtx_set_mutator(ch->qtx, mutatecb, finishmutatecb, mutatearg);
return 1;
}
int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr)
{
if (!ch->addressed_mode)
return 0;
*peer_addr = ch->cur_peer_addr;
return 1;
}
int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr)
{
if (ch->state != QUIC_CHANNEL_STATE_IDLE)
return 0;
if (peer_addr == NULL || BIO_ADDR_family(peer_addr) == AF_UNSPEC) {
BIO_ADDR_clear(&ch->cur_peer_addr);
ch->addressed_mode = 0;
return 1;
}
ch->cur_peer_addr = *peer_addr;
ch->addressed_mode = 1;
return 1;
}
QUIC_REACTOR *ossl_quic_channel_get_reactor(QUIC_CHANNEL *ch)
{
return ossl_quic_port_get0_reactor(ch->port);
}
QUIC_STREAM_MAP *ossl_quic_channel_get_qsm(QUIC_CHANNEL *ch)
{
return &ch->qsm;
}
OSSL_STATM *ossl_quic_channel_get_statm(QUIC_CHANNEL *ch)
{
return &ch->statm;
}
QUIC_STREAM *ossl_quic_channel_get_stream_by_id(QUIC_CHANNEL *ch,
uint64_t stream_id)
{
return ossl_quic_stream_map_get_by_id(&ch->qsm, stream_id);
}
int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch)
{
return ch != NULL && ch->state == QUIC_CHANNEL_STATE_ACTIVE;
}
int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch)
{
return ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING;
}
static int ossl_quic_channel_is_draining(const QUIC_CHANNEL *ch)
{
return ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING;
}
static int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch)
{
return ossl_quic_channel_is_closing(ch)
|| ossl_quic_channel_is_draining(ch);
}
int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch)
{
return ch->state == QUIC_CHANNEL_STATE_TERMINATED;
}
int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch)
{
return ossl_quic_channel_is_terminating(ch)
|| ossl_quic_channel_is_terminated(ch);
}
const QUIC_TERMINATE_CAUSE *
ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch)
{
return ossl_quic_channel_is_term_any(ch) ? &ch->terminate_cause : NULL;
}
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch)
{
return ch->handshake_complete;
}
int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch)
{
return ch->handshake_confirmed;
}
QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch)
{
return ch->port->demux;
}
QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch)
{
return ch->port;
}
QUIC_ENGINE *ossl_quic_channel_get0_engine(QUIC_CHANNEL *ch)
{
return ossl_quic_port_get0_engine(ch->port);
}
CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch)
{
return ossl_quic_port_get0_mutex(ch->port);
}
int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch)
{
return ossl_quic_demux_has_pending(ch->port->demux)
|| ossl_qrx_processed_read_pending(ch->qrx);
}
/*
* QUIC Channel: Callbacks from Miscellaneous Subsidiary Components
* ================================================================
*/
/* Used by various components. */
static OSSL_TIME get_time(void *arg)
{
QUIC_CHANNEL *ch = arg;
return ossl_quic_port_get_time(ch->port);
}
/* Used by QSM. */
static uint64_t get_stream_limit(int uni, void *arg)
{
QUIC_CHANNEL *ch = arg;
return uni ? ch->max_local_streams_uni : ch->max_local_streams_bidi;
}
/*
* Called by QRX to determine if a packet is potentially invalid before trying
* to decrypt it.
*/
static int rx_late_validate(QUIC_PN pn, int pn_space, void *arg)
{
QUIC_CHANNEL *ch = arg;
/* Potential duplicates should not be processed. */
if (!ossl_ackm_is_rx_pn_processable(ch->ackm, pn, pn_space))
return 0;
return 1;
}
/*
* Triggers a TXKU (whether spontaneous or solicited). Does not check whether
* spontaneous TXKU is currently allowed.
*/
QUIC_NEEDS_LOCK
static void ch_trigger_txku(QUIC_CHANNEL *ch)
{
uint64_t next_pn
= ossl_quic_tx_packetiser_get_next_pn(ch->txp, QUIC_PN_SPACE_APP);
if (!ossl_quic_pn_valid(next_pn)
|| !ossl_qtx_trigger_key_update(ch->qtx)) {
ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,
"key update");
return;
}
ch->txku_in_progress = 1;
ch->txku_pn = next_pn;
ch->rxku_expected = ch->ku_locally_initiated;
}
QUIC_NEEDS_LOCK
static int txku_in_progress(QUIC_CHANNEL *ch)
{
if (ch->txku_in_progress
&& ossl_ackm_get_largest_acked(ch->ackm, QUIC_PN_SPACE_APP) >= ch->txku_pn) {
OSSL_TIME pto = ossl_ackm_get_pto_duration(ch->ackm);
/*
* RFC 9001 s. 6.5: Endpoints SHOULD wait three times the PTO before
* initiating a key update after receiving an acknowledgment that
* confirms that the previous key update was received.
*
* Note that by the above wording, this period starts from when we get
* the ack for a TXKU-triggering packet, not when the TXKU is initiated.
* So we defer TXKU cooldown deadline calculation to this point.
*/
ch->txku_in_progress = 0;
ch->txku_cooldown_deadline = ossl_time_add(get_time(ch),
ossl_time_multiply(pto, 3));
}
return ch->txku_in_progress;
}
QUIC_NEEDS_LOCK
static int txku_allowed(QUIC_CHANNEL *ch)
{
return ch->tx_enc_level == QUIC_ENC_LEVEL_1RTT /* Sanity check. */
/* Strict RFC 9001 criterion for TXKU. */
&& ch->handshake_confirmed
&& !txku_in_progress(ch);
}
QUIC_NEEDS_LOCK
static int txku_recommendable(QUIC_CHANNEL *ch)
{
if (!txku_allowed(ch))
return 0;
return
/* Recommended RFC 9001 criterion for TXKU. */
ossl_time_compare(get_time(ch), ch->txku_cooldown_deadline) >= 0
/* Some additional sensible criteria. */
&& !ch->rxku_in_progress
&& !ch->rxku_pending_confirm;
}
QUIC_NEEDS_LOCK
static int txku_desirable(QUIC_CHANNEL *ch)
{
uint64_t cur_pkt_count, max_pkt_count, thresh_pkt_count;
const uint32_t enc_level = QUIC_ENC_LEVEL_1RTT;
/* Check AEAD limit to determine if we should perform a spontaneous TXKU. */
cur_pkt_count = ossl_qtx_get_cur_epoch_pkt_count(ch->qtx, enc_level);
max_pkt_count = ossl_qtx_get_max_epoch_pkt_count(ch->qtx, enc_level);
thresh_pkt_count = max_pkt_count / 2;
if (ch->txku_threshold_override != UINT64_MAX)
thresh_pkt_count = ch->txku_threshold_override;
return cur_pkt_count >= thresh_pkt_count;
}
QUIC_NEEDS_LOCK
static void ch_maybe_trigger_spontaneous_txku(QUIC_CHANNEL *ch)
{
if (!txku_recommendable(ch) || !txku_desirable(ch))
return;
ch->ku_locally_initiated = 1;
ch_trigger_txku(ch);
}
QUIC_NEEDS_LOCK
static int rxku_allowed(QUIC_CHANNEL *ch)
{
/*
* RFC 9001 s. 6.1: An endpoint MUST NOT initiate a key update prior to
* having confirmed the handshake (Section 4.1.2).
*
* RFC 9001 s. 6.1: An endpoint MUST NOT initiate a subsequent key update
* unless it has received an acknowledgment for a packet that was sent
* protected with keys from the current key phase.
*
* RFC 9001 s. 6.2: If an endpoint detects a second update before it has
* sent any packets with updated keys containing an acknowledgment for the
* packet that initiated the key update, it indicates that its peer has
* updated keys twice without awaiting confirmation. An endpoint MAY treat
* such consecutive key updates as a connection error of type
* KEY_UPDATE_ERROR.
*/
return ch->handshake_confirmed && !ch->rxku_pending_confirm;
}
/*
* Called when the QRX detects a new RX key update event.
*/
enum rxku_decision {
DECISION_RXKU_ONLY,
DECISION_PROTOCOL_VIOLATION,
DECISION_SOLICITED_TXKU
};
/* Called when the QRX detects a key update has occurred. */
QUIC_NEEDS_LOCK
static void rxku_detected(QUIC_PN pn, void *arg)
{
QUIC_CHANNEL *ch = arg;
enum rxku_decision decision;
OSSL_TIME pto;
/*
* Note: rxku_in_progress is always 0 here as an RXKU cannot be detected
* when we are still in UPDATING or COOLDOWN (see quic_record_rx.h).
*/
assert(!ch->rxku_in_progress);
if (!rxku_allowed(ch))
/* Is RXKU even allowed at this time? */
decision = DECISION_PROTOCOL_VIOLATION;
else if (ch->ku_locally_initiated)
/*
* If this key update was locally initiated (meaning that this detected
* RXKU event is a result of our own spontaneous TXKU), we do not
* trigger another TXKU; after all, to do so would result in an infinite
* ping-pong of key updates. We still process it as an RXKU.
*/
decision = DECISION_RXKU_ONLY;
else
/*
* Otherwise, a peer triggering a KU means we have to trigger a KU also.
*/
decision = DECISION_SOLICITED_TXKU;
if (decision == DECISION_PROTOCOL_VIOLATION) {
ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_KEY_UPDATE_ERROR,
0, "RX key update again too soon");
return;
}
pto = ossl_ackm_get_pto_duration(ch->ackm);
ch->ku_locally_initiated = 0;
ch->rxku_in_progress = 1;
ch->rxku_pending_confirm = 1;
ch->rxku_trigger_pn = pn;
ch->rxku_update_end_deadline = ossl_time_add(get_time(ch), pto);
ch->rxku_expected = 0;
if (decision == DECISION_SOLICITED_TXKU)
/* NOT gated by usual txku_allowed() */
ch_trigger_txku(ch);
/*
* Ordinarily, we only generate ACK when some ACK-eliciting frame has been
* received. In some cases, this may not occur for a long time, for example
* if transmission of application data is going in only one direction and
* nothing else is happening with the connection. However, since the peer
* cannot initiate a subsequent (spontaneous) TXKU until its prior
* (spontaneous or solicited) TXKU has completed - meaning that prior
* TXKU's trigger packet (or subsequent packet) has been acknowledged, this
* can lead to very long times before a TXKU is considered 'completed'.
* Optimise this by forcing ACK generation after triggering TXKU.
* (Basically, we consider a RXKU event something that is 'ACK-eliciting',
* which it more or less should be; it is necessarily separate from ordinary
* processing of ACK-eliciting frames as key update is not indicated via a
* frame.)
*/
ossl_quic_tx_packetiser_schedule_ack(ch->txp, QUIC_PN_SPACE_APP);
}
/* Called per tick to handle RXKU timer events. */
QUIC_NEEDS_LOCK
static void ch_rxku_tick(QUIC_CHANNEL *ch)
{
if (!ch->rxku_in_progress
|| ossl_time_compare(get_time(ch), ch->rxku_update_end_deadline) < 0)
return;
ch->rxku_update_end_deadline = ossl_time_infinite();
ch->rxku_in_progress = 0;
if (!ossl_qrx_key_update_timeout(ch->qrx, /*normal=*/1))
ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_INTERNAL_ERROR, 0,
"RXKU cooldown internal error");
}
QUIC_NEEDS_LOCK
static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,
void *arg)
{
QUIC_CHANNEL *ch = arg;
if (pn_space != QUIC_PN_SPACE_APP || !ch->rxku_pending_confirm
|| !ossl_quic_frame_ack_contains_pn(ack, ch->rxku_trigger_pn))
return;
/*
* Defer clearing rxku_pending_confirm until TXP generate call returns
* successfully.
*/
ch->rxku_pending_confirm_done = 1;
}
/*
* QUIC Channel: Handshake Layer Event Handling
* ============================================
*/
static int ch_on_crypto_send(const unsigned char *buf, size_t buf_len,
size_t *consumed, void *arg)
{
int ret;
QUIC_CHANNEL *ch = arg;
uint32_t enc_level = ch->tx_enc_level;
uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
QUIC_SSTREAM *sstream = ch->crypto_send[pn_space];
if (!ossl_assert(sstream != NULL))
return 0;
ret = ossl_quic_sstream_append(sstream, buf, buf_len, consumed);
return ret;
}
static int crypto_ensure_empty(QUIC_RSTREAM *rstream)
{
size_t avail = 0;
int is_fin = 0;
if (rstream == NULL)
return 1;
if (!ossl_quic_rstream_available(rstream, &avail, &is_fin))
return 0;
return avail == 0;
}
static int ch_on_crypto_recv_record(const unsigned char **buf,
size_t *bytes_read, void *arg)
{
QUIC_CHANNEL *ch = arg;
QUIC_RSTREAM *rstream;
int is_fin = 0; /* crypto stream is never finished, so we don't use this */
uint32_t i;
/*
* After we move to a later EL we must not allow our peer to send any new
* bytes in the crypto stream on a previous EL. Retransmissions of old bytes
* are allowed.
*
* In practice we will only move to a new EL when we have consumed all bytes
* which should be sent on the crypto stream at a previous EL. For example,
* the Handshake EL should not be provisioned until we have completely
* consumed a TLS 1.3 ServerHello. Thus when we provision an EL the output
* of ossl_quic_rstream_available() should be 0 for all lower ELs. Thus if a
* given EL is available we simply ensure we have not received any further
* bytes at a lower EL.
*/
for (i = QUIC_ENC_LEVEL_INITIAL; i < ch->rx_enc_level; ++i)
if (i != QUIC_ENC_LEVEL_0RTT &&
!crypto_ensure_empty(ch->crypto_recv[ossl_quic_enc_level_to_pn_space(i)])) {
/* Protocol violation (RFC 9001 s. 4.1.3) */
ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
OSSL_QUIC_FRAME_TYPE_CRYPTO,
"crypto stream data in wrong EL");
return 0;
}
rstream = ch->crypto_recv[ossl_quic_enc_level_to_pn_space(ch->rx_enc_level)];
if (rstream == NULL)
return 0;
return ossl_quic_rstream_get_record(rstream, buf, bytes_read,
&is_fin);
}
static int ch_on_crypto_release_record(size_t bytes_read, void *arg)
{
QUIC_CHANNEL *ch = arg;
QUIC_RSTREAM *rstream;
OSSL_RTT_INFO rtt_info;
uint32_t rx_pn_space = ossl_quic_enc_level_to_pn_space(ch->rx_enc_level);
rstream = ch->crypto_recv[rx_pn_space];
if (rstream == NULL)
return 0;
ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(ch), &rtt_info);
if (!ossl_quic_rxfc_on_retire(&ch->crypto_rxfc[rx_pn_space], bytes_read,
rtt_info.smoothed_rtt))
return 0;
return ossl_quic_rstream_release_record(rstream, bytes_read);
}
static int ch_on_handshake_yield_secret(uint32_t enc_level, int direction,
uint32_t suite_id, EVP_MD *md,
const unsigned char *secret,
size_t secret_len,
void *arg)
{
QUIC_CHANNEL *ch = arg;
uint32_t i;
if (enc_level < QUIC_ENC_LEVEL_HANDSHAKE || enc_level >= QUIC_ENC_LEVEL_NUM)
/* Invalid EL. */
return 0;
if (direction) {
/* TX */
if (enc_level <= ch->tx_enc_level)
/*
* Does not make sense for us to try and provision an EL we have already
* attained.
*/
return 0;
if (!ossl_qtx_provide_secret(ch->qtx, enc_level,
suite_id, md,
secret, secret_len))
return 0;
ch->tx_enc_level = enc_level;
} else {
/* RX */
if (enc_level <= ch->rx_enc_level)
/*
* Does not make sense for us to try and provision an EL we have already
* attained.
*/
return 0;
/*
* Ensure all crypto streams for previous ELs are now empty of available
* data.
*/
for (i = QUIC_ENC_LEVEL_INITIAL; i < enc_level; ++i)
if (!crypto_ensure_empty(ch->crypto_recv[ossl_quic_enc_level_to_pn_space(i)])) {
/* Protocol violation (RFC 9001 s. 4.1.3) */
ossl_quic_channel_raise_protocol_error(ch, OSSL_QUIC_ERR_PROTOCOL_VIOLATION,
OSSL_QUIC_FRAME_TYPE_CRYPTO,
"crypto stream data in wrong EL");
return 0;
}
if (!ossl_qrx_provide_secret(ch->qrx, enc_level,