Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/ssl/quic/quic_txp.c
108106 views
1
/*
2
* Copyright 2022-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 "internal/quic_txp.h"
11
#include "internal/quic_fifd.h"
12
#include "internal/quic_stream_map.h"
13
#include "internal/quic_error.h"
14
#include "internal/common.h"
15
#include <openssl/err.h>
16
17
#define MIN_CRYPTO_HDR_SIZE 3
18
19
#define MIN_FRAME_SIZE_HANDSHAKE_DONE 1
20
#define MIN_FRAME_SIZE_MAX_DATA 2
21
#define MIN_FRAME_SIZE_ACK 5
22
#define MIN_FRAME_SIZE_CRYPTO (MIN_CRYPTO_HDR_SIZE + 1)
23
#define MIN_FRAME_SIZE_STREAM 3 /* minimum useful size (for non-FIN) */
24
#define MIN_FRAME_SIZE_MAX_STREAMS_BIDI 2
25
#define MIN_FRAME_SIZE_MAX_STREAMS_UNI 2
26
27
/*
28
* Packet Archetypes
29
* =================
30
*/
31
32
/* Generate normal packets containing most frame types, subject to EL. */
33
#define TX_PACKETISER_ARCHETYPE_NORMAL 0
34
35
/*
36
* A probe packet is different in that:
37
* - It bypasses CC, but *is* counted as in flight for purposes of CC;
38
* - It must be ACK-eliciting.
39
*/
40
#define TX_PACKETISER_ARCHETYPE_PROBE 1
41
42
/*
43
* An ACK-only packet is different in that:
44
* - It bypasses CC, and is considered a 'non-inflight' packet;
45
* - It may not contain anything other than an ACK frame, not even padding.
46
*/
47
#define TX_PACKETISER_ARCHETYPE_ACK_ONLY 2
48
49
#define TX_PACKETISER_ARCHETYPE_NUM 3
50
51
struct ossl_quic_tx_packetiser_st {
52
OSSL_QUIC_TX_PACKETISER_ARGS args;
53
54
/*
55
* Opaque initial token blob provided by caller. TXP frees using the
56
* callback when it is no longer needed.
57
*/
58
const unsigned char *initial_token;
59
size_t initial_token_len;
60
ossl_quic_initial_token_free_fn *initial_token_free_cb;
61
void *initial_token_free_cb_arg;
62
63
/* Subcomponents of the TXP that we own. */
64
QUIC_FIFD fifd; /* QUIC Frame-in-Flight Dispatcher */
65
66
/* Internal state. */
67
uint64_t next_pn[QUIC_PN_SPACE_NUM]; /* Next PN to use in given PN space. */
68
OSSL_TIME last_tx_time; /* Last time a packet was generated, or 0. */
69
70
size_t unvalidated_credit; /* Limit of data we can send until validated */
71
72
/* Internal state - frame (re)generation flags. */
73
unsigned int want_handshake_done : 1;
74
unsigned int want_max_data : 1;
75
unsigned int want_max_streams_bidi : 1;
76
unsigned int want_max_streams_uni : 1;
77
78
/* Internal state - frame (re)generation flags - per PN space. */
79
unsigned int want_ack : QUIC_PN_SPACE_NUM;
80
unsigned int force_ack_eliciting : QUIC_PN_SPACE_NUM;
81
82
/*
83
* Internal state - connection close terminal state.
84
* Once this is set, it is not unset unlike other want_ flags - we keep
85
* sending it in every packet.
86
*/
87
unsigned int want_conn_close : 1;
88
89
/* Has the handshake been completed? */
90
unsigned int handshake_complete : 1;
91
92
OSSL_QUIC_FRAME_CONN_CLOSE conn_close_frame;
93
94
/*
95
* Counts of the number of bytes received and sent while in the closing
96
* state.
97
*/
98
uint64_t closing_bytes_recv;
99
uint64_t closing_bytes_xmit;
100
101
/* Internal state - packet assembly. */
102
struct txp_el {
103
unsigned char *scratch; /* scratch buffer for packet assembly */
104
size_t scratch_len; /* number of bytes allocated for scratch */
105
OSSL_QTX_IOVEC *iovec; /* scratch iovec array for use with QTX */
106
size_t alloc_iovec; /* size of iovec array */
107
} el[QUIC_ENC_LEVEL_NUM];
108
109
/* Message callback related arguments */
110
ossl_msg_cb msg_callback;
111
void *msg_callback_arg;
112
SSL *msg_callback_ssl;
113
114
/* Callbacks. */
115
void (*ack_tx_cb)(const OSSL_QUIC_FRAME_ACK *ack,
116
uint32_t pn_space,
117
void *arg);
118
void *ack_tx_cb_arg;
119
};
120
121
/*
122
* The TX helper records state used while generating frames into packets. It
123
* enables serialization into the packet to be done "transactionally" where
124
* serialization of a frame can be rolled back if it fails midway (e.g. if it
125
* does not fit).
126
*/
127
struct tx_helper {
128
OSSL_QUIC_TX_PACKETISER *txp;
129
/*
130
* The Maximum Packet Payload Length in bytes. This is the amount of
131
* space we have to generate frames into.
132
*/
133
size_t max_ppl;
134
/*
135
* Number of bytes we have generated so far.
136
*/
137
size_t bytes_appended;
138
/*
139
* Number of scratch bytes in txp->scratch we have used so far. Some iovecs
140
* will reference this scratch buffer. When we need to use more of it (e.g.
141
* when we need to put frame headers somewhere), we append to the scratch
142
* buffer, resizing if necessary, and increase this accordingly.
143
*/
144
size_t scratch_bytes;
145
/*
146
* Bytes reserved in the MaxPPL budget. We keep this number of bytes spare
147
* until reserve_allowed is set to 1. Currently this is always at most 1, as
148
* a PING frame takes up one byte and this mechanism is only used to ensure
149
* we can encode a PING frame if we have been asked to ensure a packet is
150
* ACK-eliciting and we are unusure if we are going to add any other
151
* ACK-eliciting frames before we reach our MaxPPL budget.
152
*/
153
size_t reserve;
154
/*
155
* Number of iovecs we have currently appended. This is the number of
156
* entries valid in txp->iovec.
157
*/
158
size_t num_iovec;
159
/* The EL this TX helper is being used for. */
160
uint32_t enc_level;
161
/*
162
* Whether we are allowed to make use of the reserve bytes in our MaxPPL
163
* budget. This is used to ensure we have room to append a PING frame later
164
* if we need to. Once we know we will not need to append a PING frame, this
165
* is set to 1.
166
*/
167
unsigned int reserve_allowed : 1;
168
/*
169
* Set to 1 if we have appended a STREAM frame with an implicit length. If
170
* this happens we should never append another frame after that frame as it
171
* cannot be validly encoded. This is just a safety check.
172
*/
173
unsigned int done_implicit : 1;
174
struct {
175
/*
176
* The fields in this structure are valid if active is set, which means
177
* that a serialization transaction is currently in progress.
178
*/
179
unsigned char *data;
180
WPACKET wpkt;
181
unsigned int active : 1;
182
} txn;
183
};
184
185
static void tx_helper_rollback(struct tx_helper *h);
186
static int txp_el_ensure_iovec(struct txp_el *el, size_t num);
187
188
/* Initialises the TX helper. */
189
static int tx_helper_init(struct tx_helper *h, OSSL_QUIC_TX_PACKETISER *txp,
190
uint32_t enc_level, size_t max_ppl, size_t reserve)
191
{
192
if (reserve > max_ppl)
193
return 0;
194
195
h->txp = txp;
196
h->enc_level = enc_level;
197
h->max_ppl = max_ppl;
198
h->reserve = reserve;
199
h->num_iovec = 0;
200
h->bytes_appended = 0;
201
h->scratch_bytes = 0;
202
h->reserve_allowed = 0;
203
h->done_implicit = 0;
204
h->txn.data = NULL;
205
h->txn.active = 0;
206
207
if (max_ppl > h->txp->el[enc_level].scratch_len) {
208
unsigned char *scratch;
209
210
scratch = OPENSSL_realloc(h->txp->el[enc_level].scratch, max_ppl);
211
if (scratch == NULL)
212
return 0;
213
214
h->txp->el[enc_level].scratch = scratch;
215
h->txp->el[enc_level].scratch_len = max_ppl;
216
}
217
218
return 1;
219
}
220
221
static void tx_helper_cleanup(struct tx_helper *h)
222
{
223
if (h->txn.active)
224
tx_helper_rollback(h);
225
226
h->txp = NULL;
227
}
228
229
static void tx_helper_unrestrict(struct tx_helper *h)
230
{
231
h->reserve_allowed = 1;
232
}
233
234
/*
235
* Append an extent of memory to the iovec list. The memory must remain
236
* allocated until we finish generating the packet and call the QTX.
237
*
238
* In general, the buffers passed to this function will be from one of two
239
* ranges:
240
*
241
* - Application data contained in stream buffers managed elsewhere
242
* in the QUIC stack; or
243
*
244
* - Control frame data appended into txp->scratch using tx_helper_begin and
245
* tx_helper_commit.
246
*
247
*/
248
static int tx_helper_append_iovec(struct tx_helper *h,
249
const unsigned char *buf,
250
size_t buf_len)
251
{
252
struct txp_el *el = &h->txp->el[h->enc_level];
253
254
if (buf_len == 0)
255
return 1;
256
257
if (!ossl_assert(!h->done_implicit))
258
return 0;
259
260
if (!txp_el_ensure_iovec(el, h->num_iovec + 1))
261
return 0;
262
263
el->iovec[h->num_iovec].buf = buf;
264
el->iovec[h->num_iovec].buf_len = buf_len;
265
266
++h->num_iovec;
267
h->bytes_appended += buf_len;
268
return 1;
269
}
270
271
/*
272
* How many more bytes of space do we have left in our plaintext packet payload?
273
*/
274
static size_t tx_helper_get_space_left(struct tx_helper *h)
275
{
276
return h->max_ppl
277
- (h->reserve_allowed ? 0 : h->reserve) - h->bytes_appended;
278
}
279
280
/*
281
* Begin a control frame serialization transaction. This allows the
282
* serialization of the control frame to be backed out if it turns out it won't
283
* fit. Write the control frame to the returned WPACKET. Ensure you always
284
* call tx_helper_rollback or tx_helper_commit (or tx_helper_cleanup). Returns
285
* NULL on failure.
286
*/
287
static WPACKET *tx_helper_begin(struct tx_helper *h)
288
{
289
size_t space_left, len;
290
unsigned char *data;
291
struct txp_el *el = &h->txp->el[h->enc_level];
292
293
if (!ossl_assert(!h->txn.active))
294
return NULL;
295
296
if (!ossl_assert(!h->done_implicit))
297
return NULL;
298
299
data = (unsigned char *)el->scratch + h->scratch_bytes;
300
len = el->scratch_len - h->scratch_bytes;
301
302
space_left = tx_helper_get_space_left(h);
303
if (!ossl_assert(space_left <= len))
304
return NULL;
305
306
if (!WPACKET_init_static_len(&h->txn.wpkt, data, len, 0))
307
return NULL;
308
309
if (!WPACKET_set_max_size(&h->txn.wpkt, space_left)) {
310
WPACKET_cleanup(&h->txn.wpkt);
311
return NULL;
312
}
313
314
h->txn.data = data;
315
h->txn.active = 1;
316
return &h->txn.wpkt;
317
}
318
319
static void tx_helper_end(struct tx_helper *h, int success)
320
{
321
if (success)
322
WPACKET_finish(&h->txn.wpkt);
323
else
324
WPACKET_cleanup(&h->txn.wpkt);
325
326
h->txn.active = 0;
327
h->txn.data = NULL;
328
}
329
330
/* Abort a control frame serialization transaction. */
331
static void tx_helper_rollback(struct tx_helper *h)
332
{
333
if (!h->txn.active)
334
return;
335
336
tx_helper_end(h, 0);
337
}
338
339
/* Commit a control frame. */
340
static int tx_helper_commit(struct tx_helper *h)
341
{
342
size_t l = 0;
343
344
if (!h->txn.active)
345
return 0;
346
347
if (!WPACKET_get_total_written(&h->txn.wpkt, &l)) {
348
tx_helper_end(h, 0);
349
return 0;
350
}
351
352
if (!tx_helper_append_iovec(h, h->txn.data, l)) {
353
tx_helper_end(h, 0);
354
return 0;
355
}
356
357
if (h->txp->msg_callback != NULL && l > 0) {
358
uint64_t ftype;
359
int ctype = SSL3_RT_QUIC_FRAME_FULL;
360
PACKET pkt;
361
362
if (!PACKET_buf_init(&pkt, h->txn.data, l)
363
|| !ossl_quic_wire_peek_frame_header(&pkt, &ftype, NULL)) {
364
tx_helper_end(h, 0);
365
return 0;
366
}
367
368
if (ftype == OSSL_QUIC_FRAME_TYPE_PADDING)
369
ctype = SSL3_RT_QUIC_FRAME_PADDING;
370
else if (OSSL_QUIC_FRAME_TYPE_IS_STREAM(ftype)
371
|| ftype == OSSL_QUIC_FRAME_TYPE_CRYPTO)
372
ctype = SSL3_RT_QUIC_FRAME_HEADER;
373
374
h->txp->msg_callback(1, OSSL_QUIC1_VERSION, ctype, h->txn.data, l,
375
h->txp->msg_callback_ssl,
376
h->txp->msg_callback_arg);
377
}
378
379
h->scratch_bytes += l;
380
tx_helper_end(h, 1);
381
return 1;
382
}
383
384
struct archetype_data {
385
unsigned int allow_ack : 1;
386
unsigned int allow_ping : 1;
387
unsigned int allow_crypto : 1;
388
unsigned int allow_handshake_done : 1;
389
unsigned int allow_path_challenge : 1;
390
unsigned int allow_path_response : 1;
391
unsigned int allow_new_conn_id : 1;
392
unsigned int allow_retire_conn_id : 1;
393
unsigned int allow_stream_rel : 1;
394
unsigned int allow_conn_fc : 1;
395
unsigned int allow_conn_close : 1;
396
unsigned int allow_cfq_other : 1;
397
unsigned int allow_new_token : 1;
398
unsigned int allow_force_ack_eliciting : 1;
399
unsigned int allow_padding : 1;
400
unsigned int require_ack_eliciting : 1;
401
unsigned int bypass_cc : 1;
402
};
403
404
struct txp_pkt_geom {
405
size_t cmpl, cmppl, hwm, pkt_overhead;
406
uint32_t archetype;
407
struct archetype_data adata;
408
};
409
410
struct txp_pkt {
411
struct tx_helper h;
412
int h_valid;
413
QUIC_TXPIM_PKT *tpkt;
414
QUIC_STREAM *stream_head;
415
QUIC_PKT_HDR phdr;
416
struct txp_pkt_geom geom;
417
int force_pad;
418
};
419
420
static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
421
void *arg);
422
static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
423
QUIC_TXPIM_PKT *pkt, void *arg);
424
static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id,
425
QUIC_TXPIM_PKT *pkt, void *arg);
426
static void on_sstream_updated(uint64_t stream_id, void *arg);
427
static int sstream_is_pending(QUIC_SSTREAM *sstream);
428
static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp,
429
uint32_t enc_level,
430
uint32_t archetype,
431
uint64_t cc_limit,
432
uint32_t *conn_close_enc_level);
433
static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp);
434
static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
435
size_t pl,
436
uint32_t enc_level,
437
size_t hdr_len,
438
size_t *r);
439
static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp);
440
static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp,
441
struct txp_pkt *pkt,
442
int chosen_for_conn_close);
443
static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp,
444
uint32_t enc_level, uint32_t archetype,
445
size_t running_total);
446
static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp);
447
static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt,
448
OSSL_QUIC_TX_PACKETISER *txp);
449
static int txp_pkt_append_padding(struct txp_pkt *pkt,
450
OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes);
451
static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp, struct txp_pkt *pkt,
452
uint32_t archetype, int *txpim_pkt_reffed);
453
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
454
uint64_t cc_limit);
455
456
/**
457
* Sets the validated state of a QUIC TX packetiser.
458
*
459
* This function marks the provided QUIC TX packetiser as having its credit
460
* fully validated by setting its `unvalidated_credit` field to `SIZE_MAX`.
461
*
462
* @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
463
*/
464
void ossl_quic_tx_packetiser_set_validated(OSSL_QUIC_TX_PACKETISER *txp)
465
{
466
txp->unvalidated_credit = SIZE_MAX;
467
return;
468
}
469
470
/**
471
* Adds unvalidated credit to a QUIC TX packetiser.
472
*
473
* This function increases the unvalidated credit of the provided QUIC TX
474
* packetiser. If the current unvalidated credit is not `SIZE_MAX`, the
475
* function adds three times the specified `credit` value, ensuring it does
476
* not exceed the maximum allowable value (`SIZE_MAX - 1`). If the addition
477
* would cause an overflow, the unvalidated credit is capped at
478
* `SIZE_MAX - 1`. If the current unvalidated credit is already `SIZE_MAX`,
479
* the function does nothing.
480
*
481
* @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
482
* @param credit The amount of credit to add, multiplied by 3.
483
*/
484
void ossl_quic_tx_packetiser_add_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
485
size_t credit)
486
{
487
if (txp->unvalidated_credit != SIZE_MAX) {
488
if ((SIZE_MAX - txp->unvalidated_credit) > (credit * 3))
489
txp->unvalidated_credit += credit * 3;
490
else
491
txp->unvalidated_credit = SIZE_MAX - 1;
492
}
493
494
return;
495
}
496
497
/**
498
* Consumes unvalidated credit from a QUIC TX packetiser.
499
*
500
* This function decreases the unvalidated credit of the specified
501
* QUIC TX packetiser by the given `credit` value. If the unvalidated credit
502
* is set to `SIZE_MAX`, the function does nothing, as `SIZE_MAX` represents
503
* an unlimited credit state.
504
*
505
* @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to update.
506
* @param credit The amount of credit to consume.
507
*/
508
void ossl_quic_tx_packetiser_consume_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
509
size_t credit)
510
{
511
if (txp->unvalidated_credit != SIZE_MAX) {
512
if (txp->unvalidated_credit < credit)
513
txp->unvalidated_credit = 0;
514
else
515
txp->unvalidated_credit -= credit;
516
}
517
}
518
519
/**
520
* Checks if the QUIC TX packetiser has sufficient unvalidated credit.
521
*
522
* This function determines whether the unvalidated credit of the specified
523
* QUIC TX packetiser exceeds the required credit value (`req_credit`).
524
* If the unvalidated credit is greater than `req_credit`, the function
525
* returns 1 (true); otherwise, it returns 0 (false).
526
*
527
* @param txp A pointer to the OSSL_QUIC_TX_PACKETISER structure to check.
528
* @param req_credit The required credit value to compare against.
529
*
530
* @return 1 if the unvalidated credit exceeds `req_credit`, 0 otherwise.
531
*/
532
int ossl_quic_tx_packetiser_check_unvalidated_credit(OSSL_QUIC_TX_PACKETISER *txp,
533
size_t req_credit)
534
{
535
return (txp->unvalidated_credit > req_credit);
536
}
537
538
OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args)
539
{
540
OSSL_QUIC_TX_PACKETISER *txp;
541
542
if (args == NULL
543
|| args->qtx == NULL
544
|| args->txpim == NULL
545
|| args->cfq == NULL
546
|| args->ackm == NULL
547
|| args->qsm == NULL
548
|| args->conn_txfc == NULL
549
|| args->conn_rxfc == NULL
550
|| args->max_streams_bidi_rxfc == NULL
551
|| args->max_streams_uni_rxfc == NULL
552
|| args->protocol_version == 0) {
553
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
554
return NULL;
555
}
556
557
txp = OPENSSL_zalloc(sizeof(*txp));
558
if (txp == NULL)
559
return NULL;
560
561
txp->args = *args;
562
txp->last_tx_time = ossl_time_zero();
563
564
if (!ossl_quic_fifd_init(&txp->fifd,
565
txp->args.cfq, txp->args.ackm, txp->args.txpim,
566
get_sstream_by_id, txp,
567
on_regen_notify, txp,
568
on_confirm_notify, txp,
569
on_sstream_updated, txp,
570
args->get_qlog_cb,
571
args->get_qlog_cb_arg)) {
572
OPENSSL_free(txp);
573
return NULL;
574
}
575
576
return txp;
577
}
578
579
void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp)
580
{
581
uint32_t enc_level;
582
583
if (txp == NULL)
584
return;
585
586
ossl_quic_tx_packetiser_set_initial_token(txp, NULL, 0, NULL, NULL);
587
ossl_quic_fifd_cleanup(&txp->fifd);
588
OPENSSL_free(txp->conn_close_frame.reason);
589
590
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
591
enc_level < QUIC_ENC_LEVEL_NUM;
592
++enc_level) {
593
OPENSSL_free(txp->el[enc_level].iovec);
594
OPENSSL_free(txp->el[enc_level].scratch);
595
}
596
597
OPENSSL_free(txp);
598
}
599
600
/*
601
* Determine if an Initial packet token length is reasonable based on the
602
* current MDPL, returning 1 if it is OK.
603
*
604
* The real PMTU to the peer could differ from our (pessimistic) understanding
605
* of the PMTU, therefore it is possible we could receive an Initial token from
606
* a server in a Retry packet which is bigger than the MDPL. In this case it is
607
* impossible for us ever to make forward progress and we need to error out
608
* and fail the connection attempt.
609
*
610
* The specific boundary condition is complex: for example, after the size of
611
* the Initial token, there are the Initial packet header overheads and then
612
* encryption/AEAD tag overheads. After that, the minimum room for frame data in
613
* order to guarantee forward progress must be guaranteed. For example, a crypto
614
* stream needs to always be able to serialize at least one byte in a CRYPTO
615
* frame in order to make forward progress. Because the offset field of a CRYPTO
616
* frame uses a variable-length integer, the number of bytes needed to ensure
617
* this also varies.
618
*
619
* Rather than trying to get this boundary condition check actually right,
620
* require a reasonable amount of slack to avoid pathological behaviours. (After
621
* all, transmitting a CRYPTO stream one byte at a time is probably not
622
* desirable anyway.)
623
*
624
* We choose 160 bytes as the required margin, which is double the rough
625
* estimation of the minimum we would require to guarantee forward progress
626
* under worst case packet overheads.
627
*/
628
#define TXP_REQUIRED_TOKEN_MARGIN 160
629
630
static int txp_check_token_len(size_t token_len, size_t mdpl)
631
{
632
if (token_len == 0)
633
return 1;
634
635
if (token_len >= mdpl)
636
return 0;
637
638
if (TXP_REQUIRED_TOKEN_MARGIN >= mdpl)
639
/* (should not be possible because MDPL must be at least 1200) */
640
return 0;
641
642
if (token_len > mdpl - TXP_REQUIRED_TOKEN_MARGIN)
643
return 0;
644
645
return 1;
646
}
647
648
int ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp,
649
const unsigned char *token,
650
size_t token_len,
651
ossl_quic_initial_token_free_fn *free_cb,
652
void *free_cb_arg)
653
{
654
if (!txp_check_token_len(token_len, txp_get_mdpl(txp)))
655
return 0;
656
657
if (txp->initial_token != NULL && txp->initial_token_free_cb != NULL)
658
txp->initial_token_free_cb(txp->initial_token, txp->initial_token_len,
659
txp->initial_token_free_cb_arg);
660
661
txp->initial_token = token;
662
txp->initial_token_len = token_len;
663
txp->initial_token_free_cb = free_cb;
664
txp->initial_token_free_cb_arg = free_cb_arg;
665
return 1;
666
}
667
668
int ossl_quic_tx_packetiser_set_protocol_version(OSSL_QUIC_TX_PACKETISER *txp,
669
uint32_t protocol_version)
670
{
671
txp->args.protocol_version = protocol_version;
672
return 1;
673
}
674
675
int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp,
676
const QUIC_CONN_ID *dcid)
677
{
678
if (dcid == NULL) {
679
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
680
return 0;
681
}
682
683
txp->args.cur_dcid = *dcid;
684
return 1;
685
}
686
687
int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp,
688
const QUIC_CONN_ID *scid)
689
{
690
if (scid == NULL) {
691
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER);
692
return 0;
693
}
694
695
txp->args.cur_scid = *scid;
696
return 1;
697
}
698
699
/* Change the destination L4 address the TXP uses to send datagrams. */
700
int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
701
const BIO_ADDR *peer)
702
{
703
if (peer == NULL) {
704
BIO_ADDR_clear(&txp->args.peer);
705
return 1;
706
}
707
708
return BIO_ADDR_copy(&txp->args.peer, peer);
709
}
710
711
void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp,
712
void (*cb)(const OSSL_QUIC_FRAME_ACK *ack,
713
uint32_t pn_space,
714
void *arg),
715
void *cb_arg)
716
{
717
txp->ack_tx_cb = cb;
718
txp->ack_tx_cb_arg = cb_arg;
719
}
720
721
void ossl_quic_tx_packetiser_set_qlog_cb(OSSL_QUIC_TX_PACKETISER *txp,
722
QLOG *(*get_qlog_cb)(void *arg),
723
void *get_qlog_cb_arg)
724
{
725
ossl_quic_fifd_set_qlog_cb(&txp->fifd, get_qlog_cb, get_qlog_cb_arg);
726
}
727
728
int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
729
uint32_t enc_level)
730
{
731
if (enc_level >= QUIC_ENC_LEVEL_NUM) {
732
ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
733
return 0;
734
}
735
736
if (enc_level != QUIC_ENC_LEVEL_0RTT)
737
txp->args.crypto[ossl_quic_enc_level_to_pn_space(enc_level)] = NULL;
738
739
return 1;
740
}
741
742
void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp)
743
{
744
txp->handshake_complete = 1;
745
}
746
747
void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp)
748
{
749
txp->want_handshake_done = 1;
750
}
751
752
void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp,
753
uint32_t pn_space)
754
{
755
txp->force_ack_eliciting |= (1UL << pn_space);
756
}
757
758
void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp,
759
uint32_t pn_space)
760
{
761
txp->want_ack |= (1UL << pn_space);
762
}
763
764
#define TXP_ERR_INTERNAL 0 /* Internal (e.g. alloc) error */
765
#define TXP_ERR_SUCCESS 1 /* Success */
766
#define TXP_ERR_SPACE 2 /* Not enough room for another packet */
767
#define TXP_ERR_INPUT 3 /* Invalid/malformed input */
768
769
/*
770
* Generates a datagram by polling the various ELs to determine if they want to
771
* generate any frames, and generating a datagram which coalesces packets for
772
* any ELs which do.
773
*/
774
int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
775
QUIC_TXP_STATUS *status)
776
{
777
/*
778
* Called to generate one or more datagrams, each containing one or more
779
* packets.
780
*
781
* There are some tricky things to note here:
782
*
783
* - The TXP is only concerned with generating encrypted packets;
784
* other packets use a different path.
785
*
786
* - Any datagram containing an Initial packet must have a payload length
787
* (DPL) of at least 1200 bytes. This padding need not necessarily be
788
* found in the Initial packet.
789
*
790
* - It is desirable to be able to coalesce an Initial packet
791
* with a Handshake packet. Since, before generating the Handshake
792
* packet, we do not know how long it will be, we cannot know the
793
* correct amount of padding to ensure a DPL of at least 1200 bytes.
794
* Thus this padding must added to the Handshake packet (or whatever
795
* packet is the last in the datagram).
796
*
797
* - However, at the time that we generate the Initial packet,
798
* we do not actually know for sure that we will be followed
799
* in the datagram by another packet. For example, suppose we have
800
* some queued data (e.g. crypto stream data for the HANDSHAKE EL)
801
* it looks like we will want to send on the HANDSHAKE EL.
802
* We could assume padding will be placed in the Handshake packet
803
* subsequently and avoid adding any padding to the Initial packet
804
* (which would leave no room for the Handshake packet in the
805
* datagram).
806
*
807
* However, this is not actually a safe assumption. Suppose that we
808
* are using a link with a MDPL of 1200 bytes, the minimum allowed by
809
* QUIC. Suppose that the Initial packet consumes 1195 bytes in total.
810
* Since it is not possible to fit a Handshake packet in just 5 bytes,
811
* upon trying to add a Handshake packet after generating the Initial
812
* packet, we will discover we have no room to fit it! This is not a
813
* problem in itself as another datagram can be sent subsequently, but
814
* it is a problem because we were counting to use that packet to hold
815
* the essential padding. But if we have already finished encrypting
816
* the Initial packet, we cannot go and add padding to it anymore.
817
* This leaves us stuck.
818
*
819
* Because of this, we have to plan multiple packets simultaneously, such
820
* that we can start generating a Handshake (or 0-RTT or 1-RTT, or so on)
821
* packet while still having the option to go back and add padding to the
822
* Initial packet if it turns out to be needed.
823
*
824
* Trying to predict ahead of time (e.g. during Initial packet generation)
825
* whether we will successfully generate a subsequent packet is fraught with
826
* error as it relies on a large number of variables:
827
*
828
* - Do we have room to fit a packet header? (Consider that due to
829
* variable-length integer encoding this is highly variable and can even
830
* depend on payload length due to a variable-length Length field.)
831
*
832
* - Can we fit even a single one of the frames we want to put in this
833
* packet in the packet? (Each frame type has a bespoke encoding. While
834
* our encodings of some frame types are adaptive based on the available
835
* room - e.g. STREAM frames - ultimately all frame types have some
836
* absolute minimum number of bytes to be successfully encoded. For
837
* example, if after an Initial packet there is enough room to encode
838
* only one byte of frame data, it is quite likely we can't send any of
839
* the frames we wanted to send.) While this is not strictly a problem
840
* because we could just fill the packet with padding frames, this is a
841
* pointless packet and is wasteful.
842
*
843
* Thus we adopt a multi-phase architecture:
844
*
845
* 1. Archetype Selection: Determine desired packet archetype.
846
*
847
* 2. Packet Staging: Generation of packet information and packet payload
848
* data (frame data) into staging areas.
849
*
850
* 3. Packet Adjustment: Adjustment of staged packets, adding padding to
851
* the staged packets if needed.
852
*
853
* 4. Commit: The packets are sent to the QTX and recorded as having been
854
* sent to the FIFM.
855
*
856
*/
857
int res = 0, rc;
858
uint32_t archetype, enc_level;
859
uint32_t conn_close_enc_level = QUIC_ENC_LEVEL_NUM;
860
struct txp_pkt pkt[QUIC_ENC_LEVEL_NUM];
861
size_t pkts_done = 0;
862
uint64_t cc_limit = txp->args.cc_method->get_tx_allowance(txp->args.cc_data);
863
int need_padding = 0, txpim_pkt_reffed;
864
865
memset(status, 0, sizeof(*status));
866
867
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
868
enc_level < QUIC_ENC_LEVEL_NUM;
869
++enc_level)
870
pkt[enc_level].h_valid = 0;
871
872
/*
873
* Should not be needed, but a sanity check in case anyone else has been
874
* using the QTX.
875
*/
876
ossl_qtx_finish_dgram(txp->args.qtx);
877
878
/* 1. Archetype Selection */
879
archetype = txp_determine_archetype(txp, cc_limit);
880
881
/* 2. Packet Staging */
882
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
883
enc_level < QUIC_ENC_LEVEL_NUM;
884
++enc_level) {
885
size_t running_total = (enc_level > QUIC_ENC_LEVEL_INITIAL)
886
? pkt[enc_level - 1].geom.hwm
887
: 0;
888
889
pkt[enc_level].geom.hwm = running_total;
890
891
if (!txp_should_try_staging(txp, enc_level, archetype, cc_limit,
892
&conn_close_enc_level))
893
continue;
894
895
if (!txp_pkt_init(&pkt[enc_level], txp, enc_level, archetype,
896
running_total))
897
/*
898
* If this fails this is not a fatal error - it means the geometry
899
* planning determined there was not enough space for another
900
* packet. So just proceed with what we've already planned for.
901
*/
902
break;
903
904
rc = txp_generate_for_el(txp, &pkt[enc_level],
905
conn_close_enc_level == enc_level);
906
if (rc != TXP_ERR_SUCCESS)
907
goto out;
908
909
if (pkt[enc_level].force_pad)
910
/*
911
* txp_generate_for_el emitted a frame which forces packet padding.
912
*/
913
need_padding = 1;
914
915
pkt[enc_level].geom.hwm = running_total
916
+ pkt[enc_level].h.bytes_appended
917
+ pkt[enc_level].geom.pkt_overhead;
918
}
919
920
/* 3. Packet Adjustment */
921
if (pkt[QUIC_ENC_LEVEL_INITIAL].h_valid
922
&& pkt[QUIC_ENC_LEVEL_INITIAL].h.bytes_appended > 0)
923
/*
924
* We have an Initial packet in this datagram, so we need to make sure
925
* the total size of the datagram is adequate.
926
*/
927
need_padding = 1;
928
929
if (need_padding) {
930
size_t total_dgram_size = 0;
931
const size_t min_dpl = QUIC_MIN_INITIAL_DGRAM_LEN;
932
uint32_t pad_el = QUIC_ENC_LEVEL_NUM;
933
934
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
935
enc_level < QUIC_ENC_LEVEL_NUM;
936
++enc_level)
937
if (pkt[enc_level].h_valid && pkt[enc_level].h.bytes_appended > 0) {
938
if (pad_el == QUIC_ENC_LEVEL_NUM
939
/*
940
* We might not be able to add padding, for example if we
941
* are using the ACK_ONLY archetype.
942
*/
943
&& pkt[enc_level].geom.adata.allow_padding
944
&& !pkt[enc_level].h.done_implicit)
945
pad_el = enc_level;
946
947
txp_pkt_postgen_update_pkt_overhead(&pkt[enc_level], txp);
948
total_dgram_size += pkt[enc_level].geom.pkt_overhead
949
+ pkt[enc_level].h.bytes_appended;
950
}
951
952
if (pad_el != QUIC_ENC_LEVEL_NUM && total_dgram_size < min_dpl) {
953
size_t deficit = min_dpl - total_dgram_size;
954
955
if (!txp_pkt_append_padding(&pkt[pad_el], txp, deficit))
956
goto out;
957
958
total_dgram_size += deficit;
959
960
/*
961
* Padding frames make a packet ineligible for being a non-inflight
962
* packet.
963
*/
964
pkt[pad_el].tpkt->ackm_pkt.is_inflight = 1;
965
}
966
967
/*
968
* If we have failed to make a datagram of adequate size, for example
969
* because we have a padding requirement but are using the ACK_ONLY
970
* archetype (because we are CC limited), which precludes us from
971
* sending padding, give up on generating the datagram - there is
972
* nothing we can do.
973
*/
974
if (total_dgram_size < min_dpl) {
975
res = 1;
976
goto out;
977
}
978
}
979
980
/* 4. Commit */
981
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
982
enc_level < QUIC_ENC_LEVEL_NUM;
983
++enc_level) {
984
985
if (!pkt[enc_level].h_valid)
986
/* Did not attempt to generate a packet for this EL. */
987
continue;
988
989
if (pkt[enc_level].h.bytes_appended == 0)
990
/* Nothing was generated for this EL, so skip. */
991
continue;
992
993
if (!ossl_quic_tx_packetiser_check_unvalidated_credit(txp,
994
pkt[enc_level].h.bytes_appended)) {
995
res = TXP_ERR_SPACE;
996
goto out;
997
}
998
ossl_quic_tx_packetiser_consume_unvalidated_credit(txp, pkt[enc_level].h.bytes_appended);
999
1000
rc = txp_pkt_commit(txp, &pkt[enc_level], archetype,
1001
&txpim_pkt_reffed);
1002
if (rc) {
1003
status->sent_ack_eliciting
1004
= status->sent_ack_eliciting
1005
|| pkt[enc_level].tpkt->ackm_pkt.is_ack_eliciting;
1006
1007
if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE)
1008
status->sent_handshake
1009
= (pkt[enc_level].h_valid
1010
&& pkt[enc_level].h.bytes_appended > 0);
1011
}
1012
1013
if (txpim_pkt_reffed)
1014
pkt[enc_level].tpkt = NULL; /* don't free */
1015
1016
if (!rc)
1017
goto out;
1018
1019
++pkts_done;
1020
}
1021
1022
/* Flush & Cleanup */
1023
res = 1;
1024
out:
1025
ossl_qtx_finish_dgram(txp->args.qtx);
1026
1027
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
1028
enc_level < QUIC_ENC_LEVEL_NUM;
1029
++enc_level)
1030
txp_pkt_cleanup(&pkt[enc_level], txp);
1031
1032
status->sent_pkt = pkts_done;
1033
1034
return res;
1035
}
1036
1037
static const struct archetype_data archetypes[QUIC_ENC_LEVEL_NUM][TX_PACKETISER_ARCHETYPE_NUM] = {
1038
/* EL 0(INITIAL) */
1039
{
1040
/* EL 0(INITIAL) - Archetype 0(NORMAL) */
1041
{
1042
/*allow_ack =*/1,
1043
/*allow_ping =*/1,
1044
/*allow_crypto =*/1,
1045
/*allow_handshake_done =*/0,
1046
/*allow_path_challenge =*/0,
1047
/*allow_path_response =*/0,
1048
/*allow_new_conn_id =*/0,
1049
/*allow_retire_conn_id =*/0,
1050
/*allow_stream_rel =*/0,
1051
/*allow_conn_fc =*/0,
1052
/*allow_conn_close =*/1,
1053
/*allow_cfq_other =*/0,
1054
/*allow_new_token =*/0,
1055
/*allow_force_ack_eliciting =*/1,
1056
/*allow_padding =*/1,
1057
/*require_ack_eliciting =*/0,
1058
/*bypass_cc =*/0,
1059
},
1060
/* EL 0(INITIAL) - Archetype 1(PROBE) */
1061
{
1062
/*allow_ack =*/1,
1063
/*allow_ping =*/1,
1064
/*allow_crypto =*/1,
1065
/*allow_handshake_done =*/0,
1066
/*allow_path_challenge =*/0,
1067
/*allow_path_response =*/0,
1068
/*allow_new_conn_id =*/0,
1069
/*allow_retire_conn_id =*/0,
1070
/*allow_stream_rel =*/0,
1071
/*allow_conn_fc =*/0,
1072
/*allow_conn_close =*/1,
1073
/*allow_cfq_other =*/0,
1074
/*allow_new_token =*/0,
1075
/*allow_force_ack_eliciting =*/1,
1076
/*allow_padding =*/1,
1077
/*require_ack_eliciting =*/1,
1078
/*bypass_cc =*/1,
1079
},
1080
/* EL 0(INITIAL) - Archetype 2(ACK_ONLY) */
1081
{
1082
/*allow_ack =*/1,
1083
/*allow_ping =*/0,
1084
/*allow_crypto =*/0,
1085
/*allow_handshake_done =*/0,
1086
/*allow_path_challenge =*/0,
1087
/*allow_path_response =*/0,
1088
/*allow_new_conn_id =*/0,
1089
/*allow_retire_conn_id =*/0,
1090
/*allow_stream_rel =*/0,
1091
/*allow_conn_fc =*/0,
1092
/*allow_conn_close =*/0,
1093
/*allow_cfq_other =*/0,
1094
/*allow_new_token =*/0,
1095
/*allow_force_ack_eliciting =*/1,
1096
/*allow_padding =*/0,
1097
/*require_ack_eliciting =*/0,
1098
/*bypass_cc =*/1,
1099
},
1100
},
1101
/* EL 1(0RTT) */
1102
{
1103
/* EL 1(0RTT) - Archetype 0(NORMAL) */
1104
{
1105
/*allow_ack =*/0,
1106
/*allow_ping =*/1,
1107
/*allow_crypto =*/0,
1108
/*allow_handshake_done =*/0,
1109
/*allow_path_challenge =*/0,
1110
/*allow_path_response =*/0,
1111
/*allow_new_conn_id =*/1,
1112
/*allow_retire_conn_id =*/1,
1113
/*allow_stream_rel =*/1,
1114
/*allow_conn_fc =*/1,
1115
/*allow_conn_close =*/1,
1116
/*allow_cfq_other =*/0,
1117
/*allow_new_token =*/0,
1118
/*allow_force_ack_eliciting =*/0,
1119
/*allow_padding =*/1,
1120
/*require_ack_eliciting =*/0,
1121
/*bypass_cc =*/0,
1122
},
1123
/* EL 1(0RTT) - Archetype 1(PROBE) */
1124
{
1125
/*allow_ack =*/0,
1126
/*allow_ping =*/1,
1127
/*allow_crypto =*/0,
1128
/*allow_handshake_done =*/0,
1129
/*allow_path_challenge =*/0,
1130
/*allow_path_response =*/0,
1131
/*allow_new_conn_id =*/1,
1132
/*allow_retire_conn_id =*/1,
1133
/*allow_stream_rel =*/1,
1134
/*allow_conn_fc =*/1,
1135
/*allow_conn_close =*/1,
1136
/*allow_cfq_other =*/0,
1137
/*allow_new_token =*/0,
1138
/*allow_force_ack_eliciting =*/0,
1139
/*allow_padding =*/1,
1140
/*require_ack_eliciting =*/1,
1141
/*bypass_cc =*/1,
1142
},
1143
/* EL 1(0RTT) - Archetype 2(ACK_ONLY) */
1144
{
1145
/*allow_ack =*/0,
1146
/*allow_ping =*/0,
1147
/*allow_crypto =*/0,
1148
/*allow_handshake_done =*/0,
1149
/*allow_path_challenge =*/0,
1150
/*allow_path_response =*/0,
1151
/*allow_new_conn_id =*/0,
1152
/*allow_retire_conn_id =*/0,
1153
/*allow_stream_rel =*/0,
1154
/*allow_conn_fc =*/0,
1155
/*allow_conn_close =*/0,
1156
/*allow_cfq_other =*/0,
1157
/*allow_new_token =*/0,
1158
/*allow_force_ack_eliciting =*/0,
1159
/*allow_padding =*/0,
1160
/*require_ack_eliciting =*/0,
1161
/*bypass_cc =*/1,
1162
},
1163
},
1164
/* EL (HANDSHAKE) */
1165
{
1166
/* EL 2(HANDSHAKE) - Archetype 0(NORMAL) */
1167
{
1168
/*allow_ack =*/1,
1169
/*allow_ping =*/1,
1170
/*allow_crypto =*/1,
1171
/*allow_handshake_done =*/0,
1172
/*allow_path_challenge =*/0,
1173
/*allow_path_response =*/0,
1174
/*allow_new_conn_id =*/0,
1175
/*allow_retire_conn_id =*/0,
1176
/*allow_stream_rel =*/0,
1177
/*allow_conn_fc =*/0,
1178
/*allow_conn_close =*/1,
1179
/*allow_cfq_other =*/0,
1180
/*allow_new_token =*/0,
1181
/*allow_force_ack_eliciting =*/1,
1182
/*allow_padding =*/1,
1183
/*require_ack_eliciting =*/0,
1184
/*bypass_cc =*/0,
1185
},
1186
/* EL 2(HANDSHAKE) - Archetype 1(PROBE) */
1187
{
1188
/*allow_ack =*/1,
1189
/*allow_ping =*/1,
1190
/*allow_crypto =*/1,
1191
/*allow_handshake_done =*/0,
1192
/*allow_path_challenge =*/0,
1193
/*allow_path_response =*/0,
1194
/*allow_new_conn_id =*/0,
1195
/*allow_retire_conn_id =*/0,
1196
/*allow_stream_rel =*/0,
1197
/*allow_conn_fc =*/0,
1198
/*allow_conn_close =*/1,
1199
/*allow_cfq_other =*/0,
1200
/*allow_new_token =*/0,
1201
/*allow_force_ack_eliciting =*/1,
1202
/*allow_padding =*/1,
1203
/*require_ack_eliciting =*/1,
1204
/*bypass_cc =*/1,
1205
},
1206
/* EL 2(HANDSHAKE) - Archetype 2(ACK_ONLY) */
1207
{
1208
/*allow_ack =*/1,
1209
/*allow_ping =*/0,
1210
/*allow_crypto =*/0,
1211
/*allow_handshake_done =*/0,
1212
/*allow_path_challenge =*/0,
1213
/*allow_path_response =*/0,
1214
/*allow_new_conn_id =*/0,
1215
/*allow_retire_conn_id =*/0,
1216
/*allow_stream_rel =*/0,
1217
/*allow_conn_fc =*/0,
1218
/*allow_conn_close =*/0,
1219
/*allow_cfq_other =*/0,
1220
/*allow_new_token =*/0,
1221
/*allow_force_ack_eliciting =*/1,
1222
/*allow_padding =*/0,
1223
/*require_ack_eliciting =*/0,
1224
/*bypass_cc =*/1,
1225
},
1226
},
1227
/* EL 3(1RTT) */
1228
{
1229
/* EL 3(1RTT) - Archetype 0(NORMAL) */
1230
{
1231
/*allow_ack =*/1,
1232
/*allow_ping =*/1,
1233
/*allow_crypto =*/1,
1234
/*allow_handshake_done =*/1,
1235
/*allow_path_challenge =*/0,
1236
/*allow_path_response =*/1,
1237
/*allow_new_conn_id =*/1,
1238
/*allow_retire_conn_id =*/1,
1239
/*allow_stream_rel =*/1,
1240
/*allow_conn_fc =*/1,
1241
/*allow_conn_close =*/1,
1242
/*allow_cfq_other =*/1,
1243
/*allow_new_token =*/1,
1244
/*allow_force_ack_eliciting =*/1,
1245
/*allow_padding =*/1,
1246
/*require_ack_eliciting =*/0,
1247
/*bypass_cc =*/0,
1248
},
1249
/* EL 3(1RTT) - Archetype 1(PROBE) */
1250
{
1251
/*allow_ack =*/1,
1252
/*allow_ping =*/1,
1253
/*allow_crypto =*/1,
1254
/*allow_handshake_done =*/1,
1255
/*allow_path_challenge =*/0,
1256
/*allow_path_response =*/1,
1257
/*allow_new_conn_id =*/1,
1258
/*allow_retire_conn_id =*/1,
1259
/*allow_stream_rel =*/1,
1260
/*allow_conn_fc =*/1,
1261
/*allow_conn_close =*/1,
1262
/*allow_cfq_other =*/1,
1263
/*allow_new_token =*/1,
1264
/*allow_force_ack_eliciting =*/1,
1265
/*allow_padding =*/1,
1266
/*require_ack_eliciting =*/1,
1267
/*bypass_cc =*/1,
1268
},
1269
/* EL 3(1RTT) - Archetype 2(ACK_ONLY) */
1270
{
1271
/*allow_ack =*/1,
1272
/*allow_ping =*/0,
1273
/*allow_crypto =*/0,
1274
/*allow_handshake_done =*/0,
1275
/*allow_path_challenge =*/0,
1276
/*allow_path_response =*/0,
1277
/*allow_new_conn_id =*/0,
1278
/*allow_retire_conn_id =*/0,
1279
/*allow_stream_rel =*/0,
1280
/*allow_conn_fc =*/0,
1281
/*allow_conn_close =*/0,
1282
/*allow_cfq_other =*/0,
1283
/*allow_new_token =*/0,
1284
/*allow_force_ack_eliciting =*/1,
1285
/*allow_padding =*/0,
1286
/*require_ack_eliciting =*/0,
1287
/*bypass_cc =*/1,
1288
} }
1289
};
1290
1291
static int txp_get_archetype_data(uint32_t enc_level,
1292
uint32_t archetype,
1293
struct archetype_data *a)
1294
{
1295
if (enc_level >= QUIC_ENC_LEVEL_NUM
1296
|| archetype >= TX_PACKETISER_ARCHETYPE_NUM)
1297
return 0;
1298
1299
/* No need to avoid copying this as it should not exceed one int in size. */
1300
*a = archetypes[enc_level][archetype];
1301
return 1;
1302
}
1303
1304
static int txp_determine_geometry(OSSL_QUIC_TX_PACKETISER *txp,
1305
uint32_t archetype,
1306
uint32_t enc_level,
1307
size_t running_total,
1308
QUIC_PKT_HDR *phdr,
1309
struct txp_pkt_geom *geom)
1310
{
1311
size_t mdpl, cmpl, hdr_len;
1312
1313
/* Get information about packet archetype. */
1314
if (!txp_get_archetype_data(enc_level, archetype, &geom->adata))
1315
return 0;
1316
1317
/* Assemble packet header. */
1318
phdr->type = ossl_quic_enc_level_to_pkt_type(enc_level);
1319
phdr->spin_bit = 0;
1320
phdr->pn_len = txp_determine_pn_len(txp);
1321
phdr->partial = 0;
1322
phdr->fixed = 1;
1323
phdr->reserved = 0;
1324
phdr->version = txp->args.protocol_version;
1325
phdr->dst_conn_id = txp->args.cur_dcid;
1326
phdr->src_conn_id = txp->args.cur_scid;
1327
1328
/*
1329
* We need to know the length of the payload to get an accurate header
1330
* length for non-1RTT packets, because the Length field found in
1331
* Initial/Handshake/0-RTT packets uses a variable-length encoding. However,
1332
* we don't have a good idea of the length of our payload, because the
1333
* length of the payload depends on the room in the datagram after fitting
1334
* the header, which depends on the size of the header.
1335
*
1336
* In general, it does not matter if a packet is slightly shorter (because
1337
* e.g. we predicted use of a 2-byte length field, but ended up only needing
1338
* a 1-byte length field). However this does matter for Initial packets
1339
* which must be at least 1200 bytes, which is also the assumed default MTU;
1340
* therefore in many cases Initial packets will be padded to 1200 bytes,
1341
* which means if we overestimated the header size, we will be short by a
1342
* few bytes and the server will ignore the packet for being too short. In
1343
* this case, however, such packets always *will* be padded to meet 1200
1344
* bytes, which requires a 2-byte length field, so we don't actually need to
1345
* worry about this. Thus we estimate the header length assuming a 2-byte
1346
* length field here, which should in practice work well in all cases.
1347
*/
1348
phdr->len = OSSL_QUIC_VLINT_2B_MAX - phdr->pn_len;
1349
1350
if (enc_level == QUIC_ENC_LEVEL_INITIAL) {
1351
phdr->token = txp->initial_token;
1352
phdr->token_len = txp->initial_token_len;
1353
} else {
1354
phdr->token = NULL;
1355
phdr->token_len = 0;
1356
}
1357
1358
hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(phdr->dst_conn_id.id_len,
1359
phdr);
1360
if (hdr_len == 0)
1361
return 0;
1362
1363
/* MDPL: Maximum datagram payload length. */
1364
mdpl = txp_get_mdpl(txp);
1365
1366
/*
1367
* CMPL: Maximum encoded packet size we can put into this datagram given any
1368
* previous packets coalesced into it.
1369
*/
1370
if (running_total > mdpl)
1371
/* Should not be possible, but if it happens: */
1372
cmpl = 0;
1373
else
1374
cmpl = mdpl - running_total;
1375
1376
/* CMPPL: Maximum amount we can put into the current packet payload */
1377
if (!txp_determine_ppl_from_pl(txp, cmpl, enc_level, hdr_len, &geom->cmppl))
1378
return 0;
1379
1380
geom->cmpl = cmpl;
1381
geom->pkt_overhead = cmpl - geom->cmppl;
1382
geom->archetype = archetype;
1383
return 1;
1384
}
1385
1386
static uint32_t txp_determine_archetype(OSSL_QUIC_TX_PACKETISER *txp,
1387
uint64_t cc_limit)
1388
{
1389
OSSL_ACKM_PROBE_INFO *probe_info
1390
= ossl_ackm_get0_probe_request(txp->args.ackm);
1391
uint32_t pn_space;
1392
1393
/*
1394
* If ACKM has requested probe generation (e.g. due to PTO), we generate a
1395
* Probe-archetype packet. Actually, we determine archetype on a
1396
* per-datagram basis, so if any EL wants a probe, do a pass in which
1397
* we try and generate a probe (if needed) for all ELs.
1398
*/
1399
if (probe_info->anti_deadlock_initial > 0
1400
|| probe_info->anti_deadlock_handshake > 0)
1401
return TX_PACKETISER_ARCHETYPE_PROBE;
1402
1403
for (pn_space = QUIC_PN_SPACE_INITIAL;
1404
pn_space < QUIC_PN_SPACE_NUM;
1405
++pn_space)
1406
if (probe_info->pto[pn_space] > 0)
1407
return TX_PACKETISER_ARCHETYPE_PROBE;
1408
1409
/*
1410
* If we are out of CC budget, we cannot send a normal packet,
1411
* but we can do an ACK-only packet (potentially, if we
1412
* want to send an ACK).
1413
*/
1414
if (cc_limit == 0)
1415
return TX_PACKETISER_ARCHETYPE_ACK_ONLY;
1416
1417
/* All other packets. */
1418
return TX_PACKETISER_ARCHETYPE_NORMAL;
1419
}
1420
1421
static int txp_should_try_staging(OSSL_QUIC_TX_PACKETISER *txp,
1422
uint32_t enc_level,
1423
uint32_t archetype,
1424
uint64_t cc_limit,
1425
uint32_t *conn_close_enc_level)
1426
{
1427
struct archetype_data a;
1428
uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
1429
QUIC_CFQ_ITEM *cfq_item;
1430
1431
if (!ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level))
1432
return 0;
1433
1434
if (!txp_get_archetype_data(enc_level, archetype, &a))
1435
return 0;
1436
1437
if (!a.bypass_cc && cc_limit == 0)
1438
/* CC not allowing us to send. */
1439
return 0;
1440
1441
/*
1442
* We can produce CONNECTION_CLOSE frames on any EL in principle, which
1443
* means we need to choose which EL we would prefer to use. After a
1444
* connection is fully established we have only one provisioned EL and this
1445
* is a non-issue. Where multiple ELs are provisioned, it is possible the
1446
* peer does not have the keys for the EL yet, which suggests in general it
1447
* is preferable to use the lowest EL which is still provisioned.
1448
*
1449
* However (RFC 9000 s. 10.2.3 & 12.5) we are also required to not send
1450
* application CONNECTION_CLOSE frames in non-1-RTT ELs, so as to not
1451
* potentially leak application data on a connection which has yet to be
1452
* authenticated. Thus when we have an application CONNECTION_CLOSE frame
1453
* queued and need to send it on a non-1-RTT EL, we have to convert it
1454
* into a transport CONNECTION_CLOSE frame which contains no application
1455
* data. Since this loses information, it suggests we should use the 1-RTT
1456
* EL to avoid this if possible, even if a lower EL is also available.
1457
*
1458
* At the same time, just because we have the 1-RTT EL provisioned locally
1459
* does not necessarily mean the peer does, for example if a handshake
1460
* CRYPTO frame has been lost. It is fairly important that CONNECTION_CLOSE
1461
* is signalled in a way we know our peer can decrypt, as we stop processing
1462
* connection retransmission logic for real after connection close and
1463
* simply 'blindly' retransmit the same CONNECTION_CLOSE frame.
1464
*
1465
* This is not a major concern for clients, since if a client has a 1-RTT EL
1466
* provisioned the server is guaranteed to also have a 1-RTT EL provisioned.
1467
*
1468
* TODO(QUIC FUTURE): Revisit this when when have reached a decision on how
1469
* best to implement this
1470
*/
1471
if (*conn_close_enc_level > enc_level
1472
&& *conn_close_enc_level != QUIC_ENC_LEVEL_1RTT)
1473
*conn_close_enc_level = enc_level;
1474
1475
/* Do we need to send a PTO probe? */
1476
if (a.allow_force_ack_eliciting) {
1477
OSSL_ACKM_PROBE_INFO *probe_info
1478
= ossl_ackm_get0_probe_request(txp->args.ackm);
1479
1480
if ((enc_level == QUIC_ENC_LEVEL_INITIAL
1481
&& probe_info->anti_deadlock_initial > 0)
1482
|| (enc_level == QUIC_ENC_LEVEL_HANDSHAKE
1483
&& probe_info->anti_deadlock_handshake > 0)
1484
|| probe_info->pto[pn_space] > 0)
1485
return 1;
1486
}
1487
1488
/* Does the crypto stream for this EL want to produce anything? */
1489
if (a.allow_crypto && sstream_is_pending(txp->args.crypto[pn_space]))
1490
return 1;
1491
1492
/* Does the ACKM for this PN space want to produce anything? */
1493
if (a.allow_ack && (ossl_ackm_is_ack_desired(txp->args.ackm, pn_space) || (txp->want_ack & (1UL << pn_space)) != 0))
1494
return 1;
1495
1496
/* Do we need to force emission of an ACK-eliciting packet? */
1497
if (a.allow_force_ack_eliciting
1498
&& (txp->force_ack_eliciting & (1UL << pn_space)) != 0)
1499
return 1;
1500
1501
/* Does the connection-level RXFC want to produce a frame? */
1502
if (a.allow_conn_fc && (txp->want_max_data || ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0)))
1503
return 1;
1504
1505
/* Do we want to produce a MAX_STREAMS frame? */
1506
if (a.allow_conn_fc
1507
&& (txp->want_max_streams_bidi
1508
|| ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc,
1509
0)
1510
|| txp->want_max_streams_uni
1511
|| ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc,
1512
0)))
1513
return 1;
1514
1515
/* Do we want to produce a HANDSHAKE_DONE frame? */
1516
if (a.allow_handshake_done && txp->want_handshake_done)
1517
return 1;
1518
1519
/* Do we want to produce a CONNECTION_CLOSE frame? */
1520
if (a.allow_conn_close && txp->want_conn_close && *conn_close_enc_level == enc_level)
1521
/*
1522
* This is a bit of a special case since CONNECTION_CLOSE can appear in
1523
* most packet types, and when we decide we want to send it this status
1524
* isn't tied to a specific EL. So if we want to send it, we send it
1525
* only on the lowest non-dropped EL.
1526
*/
1527
return 1;
1528
1529
/* Does the CFQ have any frames queued for this PN space? */
1530
if (enc_level != QUIC_ENC_LEVEL_0RTT)
1531
for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
1532
cfq_item != NULL;
1533
cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
1534
uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
1535
1536
switch (frame_type) {
1537
case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
1538
if (a.allow_new_conn_id)
1539
return 1;
1540
break;
1541
case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
1542
if (a.allow_retire_conn_id)
1543
return 1;
1544
break;
1545
case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
1546
if (a.allow_new_token)
1547
return 1;
1548
break;
1549
case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
1550
if (a.allow_path_response)
1551
return 1;
1552
break;
1553
default:
1554
if (a.allow_cfq_other)
1555
return 1;
1556
break;
1557
}
1558
}
1559
1560
if (a.allow_stream_rel && txp->handshake_complete) {
1561
QUIC_STREAM_ITER it;
1562
1563
/* If there are any active streams, 0/1-RTT wants to produce a packet.
1564
* Whether a stream is on the active list is required to be precise
1565
* (i.e., a stream is never on the active list if we cannot produce a
1566
* frame for it), and all stream-related frames are governed by
1567
* a.allow_stream_rel (i.e., if we can send one type of stream-related
1568
* frame, we can send any of them), so we don't need to inspect
1569
* individual streams on the active list, just confirm that the active
1570
* list is non-empty.
1571
*/
1572
ossl_quic_stream_iter_init(&it, txp->args.qsm, 0);
1573
if (it.stream != NULL)
1574
return 1;
1575
}
1576
1577
return 0;
1578
}
1579
1580
static int sstream_is_pending(QUIC_SSTREAM *sstream)
1581
{
1582
OSSL_QUIC_FRAME_STREAM hdr;
1583
OSSL_QTX_IOVEC iov[2];
1584
size_t num_iov = OSSL_NELEM(iov);
1585
1586
return ossl_quic_sstream_get_stream_frame(sstream, 0, &hdr, iov, &num_iov);
1587
}
1588
1589
/* Determine how many bytes we should use for the encoded PN. */
1590
static size_t txp_determine_pn_len(OSSL_QUIC_TX_PACKETISER *txp)
1591
{
1592
return 4; /* TODO(QUIC FUTURE) */
1593
}
1594
1595
/* Determine plaintext packet payload length from payload length. */
1596
static int txp_determine_ppl_from_pl(OSSL_QUIC_TX_PACKETISER *txp,
1597
size_t pl,
1598
uint32_t enc_level,
1599
size_t hdr_len,
1600
size_t *r)
1601
{
1602
if (pl < hdr_len)
1603
return 0;
1604
1605
pl -= hdr_len;
1606
1607
if (!ossl_qtx_calculate_plaintext_payload_len(txp->args.qtx, enc_level,
1608
pl, &pl))
1609
return 0;
1610
1611
*r = pl;
1612
return 1;
1613
}
1614
1615
static size_t txp_get_mdpl(OSSL_QUIC_TX_PACKETISER *txp)
1616
{
1617
return ossl_qtx_get_mdpl(txp->args.qtx);
1618
}
1619
1620
static QUIC_SSTREAM *get_sstream_by_id(uint64_t stream_id, uint32_t pn_space,
1621
void *arg)
1622
{
1623
OSSL_QUIC_TX_PACKETISER *txp = arg;
1624
QUIC_STREAM *s;
1625
1626
if (stream_id == UINT64_MAX)
1627
return txp->args.crypto[pn_space];
1628
1629
s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1630
if (s == NULL)
1631
return NULL;
1632
1633
return s->sstream;
1634
}
1635
1636
static void on_regen_notify(uint64_t frame_type, uint64_t stream_id,
1637
QUIC_TXPIM_PKT *pkt, void *arg)
1638
{
1639
OSSL_QUIC_TX_PACKETISER *txp = arg;
1640
1641
switch (frame_type) {
1642
case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
1643
txp->want_handshake_done = 1;
1644
break;
1645
case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
1646
txp->want_max_data = 1;
1647
break;
1648
case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
1649
txp->want_max_streams_bidi = 1;
1650
break;
1651
case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
1652
txp->want_max_streams_uni = 1;
1653
break;
1654
case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
1655
txp->want_ack |= (1UL << pkt->ackm_pkt.pkt_space);
1656
break;
1657
case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA: {
1658
QUIC_STREAM *s
1659
= ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1660
1661
if (s == NULL)
1662
return;
1663
1664
s->want_max_stream_data = 1;
1665
ossl_quic_stream_map_update_state(txp->args.qsm, s);
1666
} break;
1667
case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: {
1668
QUIC_STREAM *s
1669
= ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1670
1671
if (s == NULL)
1672
return;
1673
1674
ossl_quic_stream_map_schedule_stop_sending(txp->args.qsm, s);
1675
} break;
1676
case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: {
1677
QUIC_STREAM *s
1678
= ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1679
1680
if (s == NULL)
1681
return;
1682
1683
s->want_reset_stream = 1;
1684
ossl_quic_stream_map_update_state(txp->args.qsm, s);
1685
} break;
1686
default:
1687
assert(0);
1688
break;
1689
}
1690
}
1691
1692
static int txp_need_ping(OSSL_QUIC_TX_PACKETISER *txp,
1693
uint32_t pn_space,
1694
const struct archetype_data *adata)
1695
{
1696
return adata->allow_ping
1697
&& (adata->require_ack_eliciting
1698
|| (txp->force_ack_eliciting & (1UL << pn_space)) != 0);
1699
}
1700
1701
static int txp_pkt_init(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp,
1702
uint32_t enc_level, uint32_t archetype,
1703
size_t running_total)
1704
{
1705
uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
1706
1707
if (!txp_determine_geometry(txp, archetype, enc_level,
1708
running_total, &pkt->phdr, &pkt->geom))
1709
return 0;
1710
1711
/*
1712
* Initialise TX helper. If we must be ACK eliciting, reserve 1 byte for
1713
* PING.
1714
*/
1715
if (!tx_helper_init(&pkt->h, txp, enc_level,
1716
pkt->geom.cmppl,
1717
txp_need_ping(txp, pn_space, &pkt->geom.adata) ? 1 : 0))
1718
return 0;
1719
1720
pkt->h_valid = 1;
1721
pkt->tpkt = NULL;
1722
pkt->stream_head = NULL;
1723
pkt->force_pad = 0;
1724
return 1;
1725
}
1726
1727
static void txp_pkt_cleanup(struct txp_pkt *pkt, OSSL_QUIC_TX_PACKETISER *txp)
1728
{
1729
if (!pkt->h_valid)
1730
return;
1731
1732
tx_helper_cleanup(&pkt->h);
1733
pkt->h_valid = 0;
1734
1735
if (pkt->tpkt != NULL) {
1736
ossl_quic_txpim_pkt_release(txp->args.txpim, pkt->tpkt);
1737
pkt->tpkt = NULL;
1738
}
1739
}
1740
1741
static int txp_pkt_postgen_update_pkt_overhead(struct txp_pkt *pkt,
1742
OSSL_QUIC_TX_PACKETISER *txp)
1743
{
1744
/*
1745
* After we have staged and generated our packets, but before we commit
1746
* them, it is possible for the estimated packet overhead (packet header +
1747
* AEAD tag size) to shrink slightly because we generated a short packet
1748
* whose which can be represented in fewer bytes as a variable-length
1749
* integer than we were (pessimistically) budgeting for. We need to account
1750
* for this to ensure that we get our padding calculation exactly right.
1751
*
1752
* Update pkt_overhead to be accurate now that we know how much data is
1753
* going in a packet.
1754
*/
1755
size_t hdr_len, ciphertext_len;
1756
1757
if (pkt->h.enc_level == QUIC_ENC_LEVEL_INITIAL)
1758
/*
1759
* Don't update overheads for the INITIAL EL - we have not finished
1760
* appending padding to it and would potentially miscalculate the
1761
* correct padding if we now update the pkt_overhead field to switch to
1762
* e.g. a 1-byte length field in the packet header. Since we are padding
1763
* to QUIC_MIN_INITIAL_DGRAM_LEN which requires a 2-byte length field,
1764
* this is guaranteed to be moot anyway. See comment in
1765
* txp_determine_geometry for more information.
1766
*/
1767
return 1;
1768
1769
if (!ossl_qtx_calculate_ciphertext_payload_len(txp->args.qtx, pkt->h.enc_level,
1770
pkt->h.bytes_appended,
1771
&ciphertext_len))
1772
return 0;
1773
1774
pkt->phdr.len = ciphertext_len;
1775
1776
hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(pkt->phdr.dst_conn_id.id_len,
1777
&pkt->phdr);
1778
1779
pkt->geom.pkt_overhead = hdr_len + ciphertext_len - pkt->h.bytes_appended;
1780
return 1;
1781
}
1782
1783
static void on_confirm_notify(uint64_t frame_type, uint64_t stream_id,
1784
QUIC_TXPIM_PKT *pkt, void *arg)
1785
{
1786
OSSL_QUIC_TX_PACKETISER *txp = arg;
1787
1788
switch (frame_type) {
1789
case OSSL_QUIC_FRAME_TYPE_STOP_SENDING: {
1790
QUIC_STREAM *s
1791
= ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1792
1793
if (s == NULL)
1794
return;
1795
1796
s->acked_stop_sending = 1;
1797
ossl_quic_stream_map_update_state(txp->args.qsm, s);
1798
} break;
1799
case OSSL_QUIC_FRAME_TYPE_RESET_STREAM: {
1800
QUIC_STREAM *s
1801
= ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1802
1803
if (s == NULL)
1804
return;
1805
1806
/*
1807
* We must already be in RESET_SENT or RESET_RECVD if we are
1808
* here, so we don't need to check state here.
1809
*/
1810
ossl_quic_stream_map_notify_reset_stream_acked(txp->args.qsm, s);
1811
ossl_quic_stream_map_update_state(txp->args.qsm, s);
1812
} break;
1813
default:
1814
assert(0);
1815
break;
1816
}
1817
}
1818
1819
static int txp_pkt_append_padding(struct txp_pkt *pkt,
1820
OSSL_QUIC_TX_PACKETISER *txp, size_t num_bytes)
1821
{
1822
WPACKET *wpkt;
1823
1824
if (num_bytes == 0)
1825
return 1;
1826
1827
if (!ossl_assert(pkt->h_valid))
1828
return 0;
1829
1830
if (!ossl_assert(pkt->tpkt != NULL))
1831
return 0;
1832
1833
wpkt = tx_helper_begin(&pkt->h);
1834
if (wpkt == NULL)
1835
return 0;
1836
1837
if (!ossl_quic_wire_encode_padding(wpkt, num_bytes)) {
1838
tx_helper_rollback(&pkt->h);
1839
return 0;
1840
}
1841
1842
if (!tx_helper_commit(&pkt->h))
1843
return 0;
1844
1845
pkt->tpkt->ackm_pkt.num_bytes += num_bytes;
1846
/* Cannot be non-inflight if we have a PADDING frame */
1847
pkt->tpkt->ackm_pkt.is_inflight = 1;
1848
return 1;
1849
}
1850
1851
static void on_sstream_updated(uint64_t stream_id, void *arg)
1852
{
1853
OSSL_QUIC_TX_PACKETISER *txp = arg;
1854
QUIC_STREAM *s;
1855
1856
s = ossl_quic_stream_map_get_by_id(txp->args.qsm, stream_id);
1857
if (s == NULL)
1858
return;
1859
1860
ossl_quic_stream_map_update_state(txp->args.qsm, s);
1861
}
1862
1863
/*
1864
* Returns 1 if we can send that many bytes in closing state, 0 otherwise.
1865
* Also maintains the bytes sent state if it returns a success.
1866
*/
1867
static int try_commit_conn_close(OSSL_QUIC_TX_PACKETISER *txp, size_t n)
1868
{
1869
int res;
1870
1871
/* We can always send the first connection close frame */
1872
if (txp->closing_bytes_recv == 0)
1873
return 1;
1874
1875
/*
1876
* RFC 9000 s. 10.2.1 Closing Connection State:
1877
* To avoid being used for an amplification attack, such
1878
* endpoints MUST limit the cumulative size of packets it sends
1879
* to three times the cumulative size of the packets that are
1880
* received and attributed to the connection.
1881
* and:
1882
* An endpoint in the closing state MUST either discard packets
1883
* received from an unvalidated address or limit the cumulative
1884
* size of packets it sends to an unvalidated address to three
1885
* times the size of packets it receives from that address.
1886
*/
1887
res = txp->closing_bytes_xmit + n <= txp->closing_bytes_recv * 3;
1888
1889
/*
1890
* Attribute the bytes to the connection, if we are allowed to send them
1891
* and this isn't the first closing frame.
1892
*/
1893
if (res && txp->closing_bytes_recv != 0)
1894
txp->closing_bytes_xmit += n;
1895
return res;
1896
}
1897
1898
void ossl_quic_tx_packetiser_record_received_closing_bytes(
1899
OSSL_QUIC_TX_PACKETISER *txp, size_t n)
1900
{
1901
txp->closing_bytes_recv += n;
1902
}
1903
1904
static int txp_generate_pre_token(OSSL_QUIC_TX_PACKETISER *txp,
1905
struct txp_pkt *pkt,
1906
int chosen_for_conn_close,
1907
int *can_be_non_inflight)
1908
{
1909
const uint32_t enc_level = pkt->h.enc_level;
1910
const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
1911
const struct archetype_data *a = &pkt->geom.adata;
1912
QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
1913
struct tx_helper *h = &pkt->h;
1914
const OSSL_QUIC_FRAME_ACK *ack;
1915
OSSL_QUIC_FRAME_ACK ack2;
1916
1917
tpkt->ackm_pkt.largest_acked = QUIC_PN_INVALID;
1918
1919
/* ACK Frames (Regenerate) */
1920
if (a->allow_ack
1921
&& tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_ACK
1922
&& (((txp->want_ack & (1UL << pn_space)) != 0)
1923
|| ossl_ackm_is_ack_desired(txp->args.ackm, pn_space))
1924
&& (ack = ossl_ackm_get_ack_frame(txp->args.ackm, pn_space)) != NULL) {
1925
WPACKET *wpkt = tx_helper_begin(h);
1926
1927
if (wpkt == NULL)
1928
return 0;
1929
1930
/* We do not currently support ECN */
1931
ack2 = *ack;
1932
ack2.ecn_present = 0;
1933
1934
if (ossl_quic_wire_encode_frame_ack(wpkt,
1935
txp->args.ack_delay_exponent,
1936
&ack2)) {
1937
if (!tx_helper_commit(h))
1938
return 0;
1939
1940
tpkt->had_ack_frame = 1;
1941
1942
if (ack->num_ack_ranges > 0)
1943
tpkt->ackm_pkt.largest_acked = ack->ack_ranges[0].end;
1944
1945
if (txp->ack_tx_cb != NULL)
1946
txp->ack_tx_cb(&ack2, pn_space, txp->ack_tx_cb_arg);
1947
} else {
1948
tx_helper_rollback(h);
1949
}
1950
}
1951
1952
/* CONNECTION_CLOSE Frames (Regenerate) */
1953
if (a->allow_conn_close && txp->want_conn_close && chosen_for_conn_close) {
1954
WPACKET *wpkt = tx_helper_begin(h);
1955
OSSL_QUIC_FRAME_CONN_CLOSE f, *pf = &txp->conn_close_frame;
1956
size_t l;
1957
1958
if (wpkt == NULL)
1959
return 0;
1960
1961
/*
1962
* Application CONNECTION_CLOSE frames may only be sent in the
1963
* Application PN space, as otherwise they may be sent before a
1964
* connection is authenticated and leak application data. Therefore, if
1965
* we need to send a CONNECTION_CLOSE frame in another PN space and were
1966
* given an application CONNECTION_CLOSE frame, convert it into a
1967
* transport CONNECTION_CLOSE frame, removing any sensitive application
1968
* data.
1969
*
1970
* RFC 9000 s. 10.2.3: "A CONNECTION_CLOSE of type 0x1d MUST be replaced
1971
* by a CONNECTION_CLOSE of type 0x1c when sending the frame in Initial
1972
* or Handshake packets. Otherwise, information about the application
1973
* state might be revealed. Endpoints MUST clear the value of the Reason
1974
* Phrase field and SHOULD use the APPLICATION_ERROR code when
1975
* converting to a CONNECTION_CLOSE of type 0x1c."
1976
*/
1977
if (pn_space != QUIC_PN_SPACE_APP && pf->is_app) {
1978
pf = &f;
1979
pf->is_app = 0;
1980
pf->frame_type = 0;
1981
pf->error_code = OSSL_QUIC_ERR_APPLICATION_ERROR;
1982
pf->reason = NULL;
1983
pf->reason_len = 0;
1984
}
1985
1986
if (ossl_quic_wire_encode_frame_conn_close(wpkt, pf)
1987
&& WPACKET_get_total_written(wpkt, &l)
1988
&& try_commit_conn_close(txp, l)) {
1989
if (!tx_helper_commit(h))
1990
return 0;
1991
1992
tpkt->had_conn_close = 1;
1993
*can_be_non_inflight = 0;
1994
} else {
1995
tx_helper_rollback(h);
1996
}
1997
}
1998
1999
return 1;
2000
}
2001
2002
static int try_len(size_t space_left, size_t orig_len,
2003
size_t base_hdr_len, size_t lenbytes,
2004
uint64_t maxn, size_t *hdr_len, size_t *payload_len)
2005
{
2006
size_t n;
2007
size_t maxn_ = maxn > SIZE_MAX ? SIZE_MAX : (size_t)maxn;
2008
2009
*hdr_len = base_hdr_len + lenbytes;
2010
2011
if (orig_len == 0 && space_left >= *hdr_len) {
2012
*payload_len = 0;
2013
return 1;
2014
}
2015
2016
n = orig_len;
2017
if (n > maxn_)
2018
n = maxn_;
2019
if (n + *hdr_len > space_left)
2020
n = (space_left >= *hdr_len) ? space_left - *hdr_len : 0;
2021
2022
*payload_len = n;
2023
return n > 0;
2024
}
2025
2026
static int determine_len(size_t space_left, size_t orig_len,
2027
size_t base_hdr_len,
2028
uint64_t *hlen, uint64_t *len)
2029
{
2030
int ok = 0;
2031
size_t chosen_payload_len = 0;
2032
size_t chosen_hdr_len = 0;
2033
size_t payload_len[4], hdr_len[4];
2034
int i, valid[4] = { 0 };
2035
2036
valid[0] = try_len(space_left, orig_len, base_hdr_len,
2037
1, OSSL_QUIC_VLINT_1B_MAX,
2038
&hdr_len[0], &payload_len[0]);
2039
valid[1] = try_len(space_left, orig_len, base_hdr_len,
2040
2, OSSL_QUIC_VLINT_2B_MAX,
2041
&hdr_len[1], &payload_len[1]);
2042
valid[2] = try_len(space_left, orig_len, base_hdr_len,
2043
4, OSSL_QUIC_VLINT_4B_MAX,
2044
&hdr_len[2], &payload_len[2]);
2045
valid[3] = try_len(space_left, orig_len, base_hdr_len,
2046
8, OSSL_QUIC_VLINT_8B_MAX,
2047
&hdr_len[3], &payload_len[3]);
2048
2049
for (i = OSSL_NELEM(valid) - 1; i >= 0; --i)
2050
if (valid[i] && payload_len[i] >= chosen_payload_len) {
2051
chosen_payload_len = payload_len[i];
2052
chosen_hdr_len = hdr_len[i];
2053
ok = 1;
2054
}
2055
2056
*hlen = chosen_hdr_len;
2057
*len = chosen_payload_len;
2058
return ok;
2059
}
2060
2061
/*
2062
* Given a CRYPTO frame header with accurate chdr->len and a budget
2063
* (space_left), try to find the optimal value of chdr->len to fill as much of
2064
* the budget as possible. This is slightly hairy because larger values of
2065
* chdr->len cause larger encoded sizes of the length field of the frame, which
2066
* in turn mean less space available for payload data. We check all possible
2067
* encodings and choose the optimal encoding.
2068
*/
2069
static int determine_crypto_len(struct tx_helper *h,
2070
OSSL_QUIC_FRAME_CRYPTO *chdr,
2071
size_t space_left,
2072
uint64_t *hlen,
2073
uint64_t *len)
2074
{
2075
size_t orig_len;
2076
size_t base_hdr_len; /* CRYPTO header length without length field */
2077
2078
if (chdr->len > SIZE_MAX)
2079
return 0;
2080
2081
orig_len = (size_t)chdr->len;
2082
2083
chdr->len = 0;
2084
base_hdr_len = ossl_quic_wire_get_encoded_frame_len_crypto_hdr(chdr);
2085
chdr->len = orig_len;
2086
if (base_hdr_len == 0)
2087
return 0;
2088
2089
--base_hdr_len;
2090
2091
return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
2092
}
2093
2094
static int determine_stream_len(struct tx_helper *h,
2095
OSSL_QUIC_FRAME_STREAM *shdr,
2096
size_t space_left,
2097
uint64_t *hlen,
2098
uint64_t *len)
2099
{
2100
size_t orig_len;
2101
size_t base_hdr_len; /* STREAM header length without length field */
2102
2103
if (shdr->len > SIZE_MAX)
2104
return 0;
2105
2106
orig_len = (size_t)shdr->len;
2107
2108
shdr->len = 0;
2109
base_hdr_len = ossl_quic_wire_get_encoded_frame_len_stream_hdr(shdr);
2110
shdr->len = orig_len;
2111
if (base_hdr_len == 0)
2112
return 0;
2113
2114
if (shdr->has_explicit_len)
2115
--base_hdr_len;
2116
2117
return determine_len(space_left, orig_len, base_hdr_len, hlen, len);
2118
}
2119
2120
static int txp_generate_crypto_frames(OSSL_QUIC_TX_PACKETISER *txp,
2121
struct txp_pkt *pkt,
2122
int *have_ack_eliciting)
2123
{
2124
const uint32_t enc_level = pkt->h.enc_level;
2125
const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
2126
QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
2127
struct tx_helper *h = &pkt->h;
2128
size_t num_stream_iovec;
2129
OSSL_QUIC_FRAME_STREAM shdr = { 0 };
2130
OSSL_QUIC_FRAME_CRYPTO chdr = { 0 };
2131
OSSL_QTX_IOVEC iov[2];
2132
uint64_t hdr_bytes;
2133
WPACKET *wpkt;
2134
QUIC_TXPIM_CHUNK chunk = { 0 };
2135
size_t i, space_left;
2136
2137
for (i = 0;; ++i) {
2138
space_left = tx_helper_get_space_left(h);
2139
2140
if (space_left < MIN_FRAME_SIZE_CRYPTO)
2141
return 1; /* no point trying */
2142
2143
/* Do we have any CRYPTO data waiting? */
2144
num_stream_iovec = OSSL_NELEM(iov);
2145
if (!ossl_quic_sstream_get_stream_frame(txp->args.crypto[pn_space],
2146
i, &shdr, iov,
2147
&num_stream_iovec))
2148
return 1; /* nothing to do */
2149
2150
/* Convert STREAM frame header to CRYPTO frame header */
2151
chdr.offset = shdr.offset;
2152
chdr.len = shdr.len;
2153
2154
if (chdr.len == 0)
2155
return 1; /* nothing to do */
2156
2157
/* Find best fit (header length, payload length) combination. */
2158
if (!determine_crypto_len(h, &chdr, space_left, &hdr_bytes,
2159
&chdr.len))
2160
return 1; /* can't fit anything */
2161
2162
/*
2163
* Truncate IOVs to match our chosen length.
2164
*
2165
* The length cannot be more than SIZE_MAX because this length comes
2166
* from our send stream buffer.
2167
*/
2168
ossl_quic_sstream_adjust_iov((size_t)chdr.len, iov, num_stream_iovec);
2169
2170
/*
2171
* Ensure we have enough iovecs allocated (1 for the header, up to 2 for
2172
* the stream data.)
2173
*/
2174
if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3))
2175
return 0; /* alloc error */
2176
2177
/* Encode the header. */
2178
wpkt = tx_helper_begin(h);
2179
if (wpkt == NULL)
2180
return 0; /* alloc error */
2181
2182
if (!ossl_quic_wire_encode_frame_crypto_hdr(wpkt, &chdr)) {
2183
tx_helper_rollback(h);
2184
return 1; /* can't fit */
2185
}
2186
2187
if (!tx_helper_commit(h))
2188
return 0; /* alloc error */
2189
2190
/* Add payload iovecs to the helper (infallible). */
2191
for (i = 0; i < num_stream_iovec; ++i)
2192
tx_helper_append_iovec(h, iov[i].buf, iov[i].buf_len);
2193
2194
*have_ack_eliciting = 1;
2195
tx_helper_unrestrict(h); /* no longer need PING */
2196
2197
/* Log chunk to TXPIM. */
2198
chunk.stream_id = UINT64_MAX; /* crypto stream */
2199
chunk.start = chdr.offset;
2200
chunk.end = chdr.offset + chdr.len - 1;
2201
chunk.has_fin = 0; /* Crypto stream never ends */
2202
if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
2203
return 0; /* alloc error */
2204
}
2205
}
2206
2207
struct chunk_info {
2208
OSSL_QUIC_FRAME_STREAM shdr;
2209
uint64_t orig_len;
2210
OSSL_QTX_IOVEC iov[2];
2211
size_t num_stream_iovec;
2212
int valid;
2213
};
2214
2215
static int txp_plan_stream_chunk(OSSL_QUIC_TX_PACKETISER *txp,
2216
struct tx_helper *h,
2217
QUIC_SSTREAM *sstream,
2218
QUIC_TXFC *stream_txfc,
2219
size_t skip,
2220
struct chunk_info *chunk,
2221
uint64_t consumed)
2222
{
2223
uint64_t fc_credit, fc_swm, fc_limit;
2224
2225
chunk->num_stream_iovec = OSSL_NELEM(chunk->iov);
2226
chunk->valid = ossl_quic_sstream_get_stream_frame(sstream, skip,
2227
&chunk->shdr,
2228
chunk->iov,
2229
&chunk->num_stream_iovec);
2230
if (!chunk->valid)
2231
return 1;
2232
2233
if (!ossl_assert(chunk->shdr.len > 0 || chunk->shdr.is_fin))
2234
/* Should only have 0-length chunk if FIN */
2235
return 0;
2236
2237
chunk->orig_len = chunk->shdr.len;
2238
2239
/* Clamp according to connection and stream-level TXFC. */
2240
fc_credit = ossl_quic_txfc_get_credit(stream_txfc, consumed);
2241
fc_swm = ossl_quic_txfc_get_swm(stream_txfc);
2242
fc_limit = fc_swm + fc_credit;
2243
2244
if (chunk->shdr.len > 0 && chunk->shdr.offset + chunk->shdr.len > fc_limit) {
2245
chunk->shdr.len = (fc_limit <= chunk->shdr.offset)
2246
? 0
2247
: fc_limit - chunk->shdr.offset;
2248
chunk->shdr.is_fin = 0;
2249
}
2250
2251
if (chunk->shdr.len == 0 && !chunk->shdr.is_fin) {
2252
/*
2253
* Nothing to do due to TXFC. Since SSTREAM returns chunks in ascending
2254
* order of offset we don't need to check any later chunks, so stop
2255
* iterating here.
2256
*/
2257
chunk->valid = 0;
2258
return 1;
2259
}
2260
2261
return 1;
2262
}
2263
2264
/*
2265
* Returns 0 on fatal error (e.g. allocation failure), 1 on success.
2266
* *packet_full is set to 1 if there is no longer enough room for another STREAM
2267
* frame.
2268
*/
2269
static int txp_generate_stream_frames(OSSL_QUIC_TX_PACKETISER *txp,
2270
struct txp_pkt *pkt,
2271
uint64_t id,
2272
QUIC_SSTREAM *sstream,
2273
QUIC_TXFC *stream_txfc,
2274
QUIC_STREAM *next_stream,
2275
int *have_ack_eliciting,
2276
int *packet_full,
2277
uint64_t *new_credit_consumed,
2278
uint64_t conn_consumed)
2279
{
2280
int rc = 0;
2281
struct chunk_info chunks[2] = { 0 };
2282
const uint32_t enc_level = pkt->h.enc_level;
2283
QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
2284
struct tx_helper *h = &pkt->h;
2285
OSSL_QUIC_FRAME_STREAM *shdr;
2286
WPACKET *wpkt;
2287
QUIC_TXPIM_CHUNK chunk;
2288
size_t i, j, space_left;
2289
int can_fill_payload, use_explicit_len;
2290
int could_have_following_chunk;
2291
uint64_t orig_len;
2292
uint64_t hdr_len_implicit, payload_len_implicit;
2293
uint64_t hdr_len_explicit, payload_len_explicit;
2294
uint64_t fc_swm, fc_new_hwm;
2295
2296
fc_swm = ossl_quic_txfc_get_swm(stream_txfc);
2297
fc_new_hwm = fc_swm;
2298
2299
/*
2300
* Load the first two chunks if any offered by the send stream. We retrieve
2301
* the next chunk in advance so we can determine if we need to send any more
2302
* chunks from the same stream after this one, which is needed when
2303
* determining when we can use an implicit length in a STREAM frame.
2304
*/
2305
for (i = 0; i < 2; ++i) {
2306
if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i, &chunks[i],
2307
conn_consumed))
2308
goto err;
2309
2310
if (i == 0 && !chunks[i].valid) {
2311
/* No chunks, nothing to do. */
2312
rc = 1;
2313
goto err;
2314
}
2315
chunks[i].shdr.stream_id = id;
2316
}
2317
2318
for (i = 0;; ++i) {
2319
space_left = tx_helper_get_space_left(h);
2320
2321
if (!chunks[i % 2].valid) {
2322
/* Out of chunks; we're done. */
2323
rc = 1;
2324
goto err;
2325
}
2326
2327
if (space_left < MIN_FRAME_SIZE_STREAM) {
2328
*packet_full = 1;
2329
rc = 1;
2330
goto err;
2331
}
2332
2333
if (!ossl_assert(!h->done_implicit))
2334
/*
2335
* Logic below should have ensured we didn't append an
2336
* implicit-length unless we filled the packet or didn't have
2337
* another stream to handle, so this should not be possible.
2338
*/
2339
goto err;
2340
2341
shdr = &chunks[i % 2].shdr;
2342
orig_len = chunks[i % 2].orig_len;
2343
if (i > 0)
2344
/* Load next chunk for lookahead. */
2345
if (!txp_plan_stream_chunk(txp, h, sstream, stream_txfc, i + 1,
2346
&chunks[(i + 1) % 2], conn_consumed))
2347
goto err;
2348
2349
/*
2350
* Find best fit (header length, payload length) combination for if we
2351
* use an implicit length.
2352
*/
2353
shdr->has_explicit_len = 0;
2354
hdr_len_implicit = payload_len_implicit = 0;
2355
if (!determine_stream_len(h, shdr, space_left,
2356
&hdr_len_implicit, &payload_len_implicit)) {
2357
*packet_full = 1;
2358
rc = 1;
2359
goto err; /* can't fit anything */
2360
}
2361
2362
/*
2363
* If there is a next stream, we don't use the implicit length so we can
2364
* add more STREAM frames after this one, unless there is enough data
2365
* for this STREAM frame to fill the packet.
2366
*/
2367
can_fill_payload = (hdr_len_implicit + payload_len_implicit
2368
>= space_left);
2369
2370
/*
2371
* Is there is a stream after this one, or another chunk pending
2372
* transmission in this stream?
2373
*/
2374
could_have_following_chunk
2375
= (next_stream != NULL || chunks[(i + 1) % 2].valid);
2376
2377
/* Choose between explicit or implicit length representations. */
2378
use_explicit_len = !((can_fill_payload || !could_have_following_chunk)
2379
&& !pkt->force_pad);
2380
2381
if (use_explicit_len) {
2382
/*
2383
* Find best fit (header length, payload length) combination for if
2384
* we use an explicit length.
2385
*/
2386
shdr->has_explicit_len = 1;
2387
hdr_len_explicit = payload_len_explicit = 0;
2388
if (!determine_stream_len(h, shdr, space_left,
2389
&hdr_len_explicit, &payload_len_explicit)) {
2390
*packet_full = 1;
2391
rc = 1;
2392
goto err; /* can't fit anything */
2393
}
2394
2395
shdr->len = payload_len_explicit;
2396
} else {
2397
*packet_full = 1;
2398
shdr->has_explicit_len = 0;
2399
shdr->len = payload_len_implicit;
2400
}
2401
2402
/* If this is a FIN, don't keep filling the packet with more FINs. */
2403
if (shdr->is_fin)
2404
chunks[(i + 1) % 2].valid = 0;
2405
2406
/*
2407
* We are now committed to our length (shdr->len can't change).
2408
* If we truncated the chunk, clear the FIN bit.
2409
*/
2410
if (shdr->len < orig_len)
2411
shdr->is_fin = 0;
2412
2413
/* Truncate IOVs to match our chosen length. */
2414
ossl_quic_sstream_adjust_iov((size_t)shdr->len, chunks[i % 2].iov,
2415
chunks[i % 2].num_stream_iovec);
2416
2417
/*
2418
* Ensure we have enough iovecs allocated (1 for the header, up to 2 for
2419
* the stream data.)
2420
*/
2421
if (!txp_el_ensure_iovec(&txp->el[enc_level], h->num_iovec + 3))
2422
goto err; /* alloc error */
2423
2424
/* Encode the header. */
2425
wpkt = tx_helper_begin(h);
2426
if (wpkt == NULL)
2427
goto err; /* alloc error */
2428
2429
if (!ossl_assert(ossl_quic_wire_encode_frame_stream_hdr(wpkt, shdr))) {
2430
/* (Should not be possible.) */
2431
tx_helper_rollback(h);
2432
*packet_full = 1;
2433
rc = 1;
2434
goto err; /* can't fit */
2435
}
2436
2437
if (!tx_helper_commit(h))
2438
goto err; /* alloc error */
2439
2440
/* Add payload iovecs to the helper (infallible). */
2441
for (j = 0; j < chunks[i % 2].num_stream_iovec; ++j)
2442
tx_helper_append_iovec(h, chunks[i % 2].iov[j].buf,
2443
chunks[i % 2].iov[j].buf_len);
2444
2445
*have_ack_eliciting = 1;
2446
tx_helper_unrestrict(h); /* no longer need PING */
2447
if (!shdr->has_explicit_len)
2448
h->done_implicit = 1;
2449
2450
/* Log new TXFC credit which was consumed. */
2451
if (shdr->len > 0 && shdr->offset + shdr->len > fc_new_hwm)
2452
fc_new_hwm = shdr->offset + shdr->len;
2453
2454
/* Log chunk to TXPIM. */
2455
chunk.stream_id = shdr->stream_id;
2456
chunk.start = shdr->offset;
2457
chunk.end = shdr->offset + shdr->len - 1;
2458
chunk.has_fin = shdr->is_fin;
2459
chunk.has_stop_sending = 0;
2460
chunk.has_reset_stream = 0;
2461
if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
2462
goto err; /* alloc error */
2463
2464
if (shdr->len < orig_len) {
2465
/*
2466
* If we did not serialize all of this chunk we definitely do not
2467
* want to try the next chunk
2468
*/
2469
rc = 1;
2470
goto err;
2471
}
2472
}
2473
2474
err:
2475
*new_credit_consumed = fc_new_hwm - fc_swm;
2476
return rc;
2477
}
2478
2479
static void txp_enlink_tmp(QUIC_STREAM **tmp_head, QUIC_STREAM *stream)
2480
{
2481
stream->txp_next = *tmp_head;
2482
*tmp_head = stream;
2483
}
2484
2485
static int txp_generate_stream_related(OSSL_QUIC_TX_PACKETISER *txp,
2486
struct txp_pkt *pkt,
2487
int *have_ack_eliciting,
2488
QUIC_STREAM **tmp_head)
2489
{
2490
QUIC_STREAM_ITER it;
2491
WPACKET *wpkt;
2492
uint64_t cwm;
2493
QUIC_STREAM *stream, *snext;
2494
struct tx_helper *h = &pkt->h;
2495
uint64_t conn_consumed = 0;
2496
2497
for (ossl_quic_stream_iter_init(&it, txp->args.qsm, 1);
2498
it.stream != NULL;) {
2499
2500
stream = it.stream;
2501
ossl_quic_stream_iter_next(&it);
2502
snext = it.stream;
2503
2504
stream->txp_sent_fc = 0;
2505
stream->txp_sent_stop_sending = 0;
2506
stream->txp_sent_reset_stream = 0;
2507
stream->txp_blocked = 0;
2508
stream->txp_txfc_new_credit_consumed = 0;
2509
2510
/* Stream Abort Frames (STOP_SENDING, RESET_STREAM) */
2511
if (stream->want_stop_sending) {
2512
OSSL_QUIC_FRAME_STOP_SENDING f;
2513
2514
wpkt = tx_helper_begin(h);
2515
if (wpkt == NULL)
2516
return 0; /* alloc error */
2517
2518
f.stream_id = stream->id;
2519
f.app_error_code = stream->stop_sending_aec;
2520
if (!ossl_quic_wire_encode_frame_stop_sending(wpkt, &f)) {
2521
tx_helper_rollback(h); /* can't fit */
2522
txp_enlink_tmp(tmp_head, stream);
2523
break;
2524
}
2525
2526
if (!tx_helper_commit(h))
2527
return 0; /* alloc error */
2528
2529
*have_ack_eliciting = 1;
2530
tx_helper_unrestrict(h); /* no longer need PING */
2531
stream->txp_sent_stop_sending = 1;
2532
}
2533
2534
if (stream->want_reset_stream) {
2535
OSSL_QUIC_FRAME_RESET_STREAM f;
2536
2537
if (!ossl_assert(stream->send_state == QUIC_SSTREAM_STATE_RESET_SENT))
2538
return 0;
2539
2540
wpkt = tx_helper_begin(h);
2541
if (wpkt == NULL)
2542
return 0; /* alloc error */
2543
2544
f.stream_id = stream->id;
2545
f.app_error_code = stream->reset_stream_aec;
2546
if (!ossl_quic_stream_send_get_final_size(stream, &f.final_size))
2547
return 0; /* should not be possible */
2548
2549
if (!ossl_quic_wire_encode_frame_reset_stream(wpkt, &f)) {
2550
tx_helper_rollback(h); /* can't fit */
2551
txp_enlink_tmp(tmp_head, stream);
2552
break;
2553
}
2554
2555
if (!tx_helper_commit(h))
2556
return 0; /* alloc error */
2557
2558
*have_ack_eliciting = 1;
2559
tx_helper_unrestrict(h); /* no longer need PING */
2560
stream->txp_sent_reset_stream = 1;
2561
2562
/*
2563
* The final size of the stream as indicated by RESET_STREAM is used
2564
* to ensure a consistent view of flow control state by both
2565
* parties; if we happen to send a RESET_STREAM that consumes more
2566
* flow control credit, make sure we account for that.
2567
*/
2568
if (!ossl_assert(f.final_size <= ossl_quic_txfc_get_swm(&stream->txfc)))
2569
return 0;
2570
2571
stream->txp_txfc_new_credit_consumed
2572
= f.final_size - ossl_quic_txfc_get_swm(&stream->txfc);
2573
}
2574
2575
/*
2576
* Stream Flow Control Frames (MAX_STREAM_DATA)
2577
*
2578
* RFC 9000 s. 13.3: "An endpoint SHOULD stop sending MAX_STREAM_DATA
2579
* frames when the receiving part of the stream enters a "Size Known" or
2580
* "Reset Recvd" state." -- In practice, RECV is the only state
2581
* in which it makes sense to generate more MAX_STREAM_DATA frames.
2582
*/
2583
if (stream->recv_state == QUIC_RSTREAM_STATE_RECV
2584
&& (stream->want_max_stream_data
2585
|| ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 0))) {
2586
2587
wpkt = tx_helper_begin(h);
2588
if (wpkt == NULL)
2589
return 0; /* alloc error */
2590
2591
cwm = ossl_quic_rxfc_get_cwm(&stream->rxfc);
2592
2593
if (!ossl_quic_wire_encode_frame_max_stream_data(wpkt, stream->id,
2594
cwm)) {
2595
tx_helper_rollback(h); /* can't fit */
2596
txp_enlink_tmp(tmp_head, stream);
2597
break;
2598
}
2599
2600
if (!tx_helper_commit(h))
2601
return 0; /* alloc error */
2602
2603
*have_ack_eliciting = 1;
2604
tx_helper_unrestrict(h); /* no longer need PING */
2605
stream->txp_sent_fc = 1;
2606
}
2607
2608
/*
2609
* Stream Data Frames (STREAM)
2610
*
2611
* RFC 9000 s. 3.3: A sender MUST NOT send a STREAM [...] frame for a
2612
* stream in the "Reset Sent" state [or any terminal state]. We don't
2613
* send any more STREAM frames if we are sending, have sent, or are
2614
* planning to send, RESET_STREAM. The other terminal state is Data
2615
* Recvd, but txp_generate_stream_frames() is guaranteed to generate
2616
* nothing in this case.
2617
*/
2618
if (ossl_quic_stream_has_send_buffer(stream)
2619
&& !ossl_quic_stream_send_is_reset(stream)) {
2620
int packet_full = 0;
2621
2622
if (!ossl_assert(!stream->want_reset_stream))
2623
return 0;
2624
2625
if (!txp_generate_stream_frames(txp, pkt,
2626
stream->id, stream->sstream,
2627
&stream->txfc,
2628
snext,
2629
have_ack_eliciting,
2630
&packet_full,
2631
&stream->txp_txfc_new_credit_consumed,
2632
conn_consumed)) {
2633
/* Fatal error (allocation, etc.) */
2634
txp_enlink_tmp(tmp_head, stream);
2635
return 0;
2636
}
2637
conn_consumed += stream->txp_txfc_new_credit_consumed;
2638
2639
if (packet_full) {
2640
txp_enlink_tmp(tmp_head, stream);
2641
break;
2642
}
2643
}
2644
2645
txp_enlink_tmp(tmp_head, stream);
2646
}
2647
2648
return 1;
2649
}
2650
2651
static int txp_generate_for_el(OSSL_QUIC_TX_PACKETISER *txp,
2652
struct txp_pkt *pkt,
2653
int chosen_for_conn_close)
2654
{
2655
int rc = TXP_ERR_SUCCESS;
2656
const uint32_t enc_level = pkt->h.enc_level;
2657
const uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
2658
int have_ack_eliciting = 0, done_pre_token = 0;
2659
const struct archetype_data a = pkt->geom.adata;
2660
/*
2661
* Cleared if we encode any non-ACK-eliciting frame type which rules out the
2662
* packet being a non-inflight frame. This means any non-ACK ACK-eliciting
2663
* frame, even PADDING frames. ACK eliciting frames always cause a packet to
2664
* become ineligible for non-inflight treatment so it is not necessary to
2665
* clear this in cases where have_ack_eliciting is set, as it is ignored in
2666
* that case.
2667
*/
2668
int can_be_non_inflight = 1;
2669
QUIC_CFQ_ITEM *cfq_item;
2670
QUIC_TXPIM_PKT *tpkt = NULL;
2671
struct tx_helper *h = &pkt->h;
2672
2673
/* Maximum PN reached? */
2674
if (!ossl_quic_pn_valid(txp->next_pn[pn_space]))
2675
goto fatal_err;
2676
2677
if (!ossl_assert(pkt->tpkt == NULL))
2678
goto fatal_err;
2679
2680
if ((pkt->tpkt = tpkt = ossl_quic_txpim_pkt_alloc(txp->args.txpim)) == NULL)
2681
goto fatal_err;
2682
2683
/*
2684
* Frame Serialization
2685
* ===================
2686
*
2687
* We now serialize frames into the packet in descending order of priority.
2688
*/
2689
2690
/* HANDSHAKE_DONE (Regenerate) */
2691
if (a.allow_handshake_done && txp->want_handshake_done
2692
&& tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_HANDSHAKE_DONE) {
2693
WPACKET *wpkt = tx_helper_begin(h);
2694
2695
if (wpkt == NULL)
2696
goto fatal_err;
2697
2698
if (ossl_quic_wire_encode_frame_handshake_done(wpkt)) {
2699
tpkt->had_handshake_done_frame = 1;
2700
have_ack_eliciting = 1;
2701
2702
if (!tx_helper_commit(h))
2703
goto fatal_err;
2704
2705
tx_helper_unrestrict(h); /* no longer need PING */
2706
} else {
2707
tx_helper_rollback(h);
2708
}
2709
}
2710
2711
/* MAX_DATA (Regenerate) */
2712
if (a.allow_conn_fc
2713
&& (txp->want_max_data
2714
|| ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 0))
2715
&& tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_DATA) {
2716
WPACKET *wpkt = tx_helper_begin(h);
2717
uint64_t cwm = ossl_quic_rxfc_get_cwm(txp->args.conn_rxfc);
2718
2719
if (wpkt == NULL)
2720
goto fatal_err;
2721
2722
if (ossl_quic_wire_encode_frame_max_data(wpkt, cwm)) {
2723
tpkt->had_max_data_frame = 1;
2724
have_ack_eliciting = 1;
2725
2726
if (!tx_helper_commit(h))
2727
goto fatal_err;
2728
2729
tx_helper_unrestrict(h); /* no longer need PING */
2730
} else {
2731
tx_helper_rollback(h);
2732
}
2733
}
2734
2735
/* MAX_STREAMS_BIDI (Regenerate) */
2736
if (a.allow_conn_fc
2737
&& (txp->want_max_streams_bidi
2738
|| ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 0))
2739
&& tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_BIDI) {
2740
WPACKET *wpkt = tx_helper_begin(h);
2741
uint64_t max_streams
2742
= ossl_quic_rxfc_get_cwm(txp->args.max_streams_bidi_rxfc);
2743
2744
if (wpkt == NULL)
2745
goto fatal_err;
2746
2747
if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/0,
2748
max_streams)) {
2749
tpkt->had_max_streams_bidi_frame = 1;
2750
have_ack_eliciting = 1;
2751
2752
if (!tx_helper_commit(h))
2753
goto fatal_err;
2754
2755
tx_helper_unrestrict(h); /* no longer need PING */
2756
} else {
2757
tx_helper_rollback(h);
2758
}
2759
}
2760
2761
/* MAX_STREAMS_UNI (Regenerate) */
2762
if (a.allow_conn_fc
2763
&& (txp->want_max_streams_uni
2764
|| ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 0))
2765
&& tx_helper_get_space_left(h) >= MIN_FRAME_SIZE_MAX_STREAMS_UNI) {
2766
WPACKET *wpkt = tx_helper_begin(h);
2767
uint64_t max_streams
2768
= ossl_quic_rxfc_get_cwm(txp->args.max_streams_uni_rxfc);
2769
2770
if (wpkt == NULL)
2771
goto fatal_err;
2772
2773
if (ossl_quic_wire_encode_frame_max_streams(wpkt, /*is_uni=*/1,
2774
max_streams)) {
2775
tpkt->had_max_streams_uni_frame = 1;
2776
have_ack_eliciting = 1;
2777
2778
if (!tx_helper_commit(h))
2779
goto fatal_err;
2780
2781
tx_helper_unrestrict(h); /* no longer need PING */
2782
} else {
2783
tx_helper_rollback(h);
2784
}
2785
}
2786
2787
/* GCR Frames */
2788
for (cfq_item = ossl_quic_cfq_get_priority_head(txp->args.cfq, pn_space);
2789
cfq_item != NULL;
2790
cfq_item = ossl_quic_cfq_item_get_priority_next(cfq_item, pn_space)) {
2791
uint64_t frame_type = ossl_quic_cfq_item_get_frame_type(cfq_item);
2792
const unsigned char *encoded = ossl_quic_cfq_item_get_encoded(cfq_item);
2793
size_t encoded_len = ossl_quic_cfq_item_get_encoded_len(cfq_item);
2794
2795
switch (frame_type) {
2796
case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
2797
if (!a.allow_new_conn_id)
2798
continue;
2799
break;
2800
case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
2801
if (!a.allow_retire_conn_id)
2802
continue;
2803
break;
2804
case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
2805
if (!a.allow_new_token)
2806
continue;
2807
2808
/*
2809
* NEW_TOKEN frames are handled via GCR, but some
2810
* Regenerate-strategy frames should come before them (namely
2811
* ACK, CONNECTION_CLOSE, PATH_CHALLENGE and PATH_RESPONSE). If
2812
* we find a NEW_TOKEN frame, do these now. If there are no
2813
* NEW_TOKEN frames in the GCR queue we will handle these below.
2814
*/
2815
if (!done_pre_token)
2816
if (txp_generate_pre_token(txp, pkt,
2817
chosen_for_conn_close,
2818
&can_be_non_inflight))
2819
done_pre_token = 1;
2820
2821
break;
2822
case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
2823
if (!a.allow_path_response)
2824
continue;
2825
2826
/*
2827
* RFC 9000 s. 8.2.2: An endpoint MUST expand datagrams that
2828
* contain a PATH_RESPONSE frame to at least the smallest
2829
* allowed maximum datagram size of 1200 bytes.
2830
*/
2831
pkt->force_pad = 1;
2832
break;
2833
default:
2834
if (!a.allow_cfq_other)
2835
continue;
2836
break;
2837
}
2838
2839
/*
2840
* If the frame is too big, don't try to schedule any more GCR frames in
2841
* this packet rather than sending subsequent ones out of order.
2842
*/
2843
if (encoded_len > tx_helper_get_space_left(h))
2844
break;
2845
2846
if (!tx_helper_append_iovec(h, encoded, encoded_len))
2847
goto fatal_err;
2848
2849
ossl_quic_txpim_pkt_add_cfq_item(tpkt, cfq_item);
2850
2851
if (ossl_quic_frame_type_is_ack_eliciting(frame_type)) {
2852
have_ack_eliciting = 1;
2853
tx_helper_unrestrict(h); /* no longer need PING */
2854
}
2855
}
2856
2857
/*
2858
* If we didn't generate ACK, CONNECTION_CLOSE, PATH_CHALLENGE or
2859
* PATH_RESPONSE (as desired) before, do so now.
2860
*/
2861
if (!done_pre_token)
2862
if (txp_generate_pre_token(txp, pkt,
2863
chosen_for_conn_close,
2864
&can_be_non_inflight))
2865
done_pre_token = 1;
2866
2867
/* CRYPTO Frames */
2868
if (a.allow_crypto)
2869
if (!txp_generate_crypto_frames(txp, pkt, &have_ack_eliciting))
2870
goto fatal_err;
2871
2872
/* Stream-specific frames */
2873
if (a.allow_stream_rel && txp->handshake_complete)
2874
if (!txp_generate_stream_related(txp, pkt,
2875
&have_ack_eliciting,
2876
&pkt->stream_head))
2877
goto fatal_err;
2878
2879
/* PING */
2880
tx_helper_unrestrict(h);
2881
2882
if (!have_ack_eliciting && txp_need_ping(txp, pn_space, &a)) {
2883
WPACKET *wpkt;
2884
2885
assert(h->reserve > 0);
2886
wpkt = tx_helper_begin(h);
2887
if (wpkt == NULL)
2888
goto fatal_err;
2889
2890
if (!ossl_quic_wire_encode_frame_ping(wpkt)
2891
|| !tx_helper_commit(h))
2892
/*
2893
* We treat a request to be ACK-eliciting as a requirement, so this
2894
* is an error.
2895
*/
2896
goto fatal_err;
2897
2898
have_ack_eliciting = 1;
2899
}
2900
2901
/* PADDING is added by ossl_quic_tx_packetiser_generate(). */
2902
2903
/*
2904
* ACKM Data
2905
* =========
2906
*/
2907
if (have_ack_eliciting)
2908
can_be_non_inflight = 0;
2909
2910
/* ACKM Data */
2911
tpkt->ackm_pkt.num_bytes = h->bytes_appended + pkt->geom.pkt_overhead;
2912
tpkt->ackm_pkt.pkt_num = txp->next_pn[pn_space];
2913
/* largest_acked is set in txp_generate_pre_token */
2914
tpkt->ackm_pkt.pkt_space = pn_space;
2915
tpkt->ackm_pkt.is_inflight = !can_be_non_inflight;
2916
tpkt->ackm_pkt.is_ack_eliciting = have_ack_eliciting;
2917
tpkt->ackm_pkt.is_pto_probe = 0;
2918
tpkt->ackm_pkt.is_mtu_probe = 0;
2919
tpkt->ackm_pkt.time = txp->args.now(txp->args.now_arg);
2920
tpkt->pkt_type = pkt->phdr.type;
2921
2922
/* Done. */
2923
return rc;
2924
2925
fatal_err:
2926
/*
2927
* Handler for fatal errors, i.e. errors causing us to abort the entire
2928
* packet rather than just one frame. Examples of such errors include
2929
* allocation errors.
2930
*/
2931
if (tpkt != NULL) {
2932
ossl_quic_txpim_pkt_release(txp->args.txpim, tpkt);
2933
pkt->tpkt = NULL;
2934
}
2935
return TXP_ERR_INTERNAL;
2936
}
2937
2938
/*
2939
* Commits and queues a packet for transmission. There is no backing out after
2940
* this.
2941
*
2942
* This:
2943
*
2944
* - Sends the packet to the QTX for encryption and transmission;
2945
*
2946
* - Records the packet as having been transmitted in FIFM. ACKM is informed,
2947
* etc. and the TXPIM record is filed.
2948
*
2949
* - Informs various subsystems of frames that were sent and clears frame
2950
* wanted flags so that we do not generate the same frames again.
2951
*
2952
* Assumptions:
2953
*
2954
* - pkt is a txp_pkt for the correct EL;
2955
*
2956
* - pkt->tpkt is valid;
2957
*
2958
* - pkt->tpkt->ackm_pkt has been fully filled in;
2959
*
2960
* - Stream chunk records have been appended to pkt->tpkt for STREAM and
2961
* CRYPTO frames, but not for RESET_STREAM or STOP_SENDING frames;
2962
*
2963
* - The chosen stream list for the packet can be fully walked from
2964
* pkt->stream_head using stream->txp_next;
2965
*
2966
* - pkt->has_ack_eliciting is set correctly.
2967
*
2968
*/
2969
static int txp_pkt_commit(OSSL_QUIC_TX_PACKETISER *txp,
2970
struct txp_pkt *pkt,
2971
uint32_t archetype,
2972
int *txpim_pkt_reffed)
2973
{
2974
int rc = 1;
2975
uint32_t enc_level = pkt->h.enc_level;
2976
uint32_t pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
2977
QUIC_TXPIM_PKT *tpkt = pkt->tpkt;
2978
QUIC_STREAM *stream;
2979
OSSL_QTX_PKT txpkt;
2980
struct archetype_data a;
2981
2982
*txpim_pkt_reffed = 0;
2983
2984
/* Cannot send a packet with an empty payload. */
2985
if (pkt->h.bytes_appended == 0)
2986
return 0;
2987
2988
if (!txp_get_archetype_data(enc_level, archetype, &a))
2989
return 0;
2990
2991
/* Packet Information for QTX */
2992
txpkt.hdr = &pkt->phdr;
2993
txpkt.iovec = txp->el[enc_level].iovec;
2994
txpkt.num_iovec = pkt->h.num_iovec;
2995
txpkt.local = NULL;
2996
txpkt.peer = BIO_ADDR_family(&txp->args.peer) == AF_UNSPEC
2997
? NULL
2998
: &txp->args.peer;
2999
txpkt.pn = txp->next_pn[pn_space];
3000
txpkt.flags = OSSL_QTX_PKT_FLAG_COALESCE; /* always try to coalesce */
3001
3002
/* Generate TXPIM chunks representing STOP_SENDING and RESET_STREAM frames. */
3003
for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next)
3004
if (stream->txp_sent_stop_sending || stream->txp_sent_reset_stream) {
3005
/* Log STOP_SENDING/RESET_STREAM chunk to TXPIM. */
3006
QUIC_TXPIM_CHUNK chunk;
3007
3008
chunk.stream_id = stream->id;
3009
chunk.start = UINT64_MAX;
3010
chunk.end = 0;
3011
chunk.has_fin = 0;
3012
chunk.has_stop_sending = stream->txp_sent_stop_sending;
3013
chunk.has_reset_stream = stream->txp_sent_reset_stream;
3014
if (!ossl_quic_txpim_pkt_append_chunk(tpkt, &chunk))
3015
return 0; /* alloc error */
3016
}
3017
3018
/* Dispatch to FIFD. */
3019
if (!ossl_quic_fifd_pkt_commit(&txp->fifd, tpkt))
3020
return 0;
3021
3022
/*
3023
* Transmission and Post-Packet Generation Bookkeeping
3024
* ===================================================
3025
*
3026
* No backing out anymore - at this point the ACKM has recorded the packet
3027
* as having been sent, so we need to increment our next PN counter, or
3028
* the ACKM will complain when we try to record a duplicate packet with
3029
* the same PN later. At this point actually sending the packet may still
3030
* fail. In this unlikely event it will simply be handled as though it
3031
* were a lost packet.
3032
*/
3033
++txp->next_pn[pn_space];
3034
*txpim_pkt_reffed = 1;
3035
3036
/* Send the packet. */
3037
if (!ossl_qtx_write_pkt(txp->args.qtx, &txpkt))
3038
return 0;
3039
3040
/*
3041
* Record FC and stream abort frames as sent; deactivate streams which no
3042
* longer have anything to do.
3043
*/
3044
for (stream = pkt->stream_head; stream != NULL; stream = stream->txp_next) {
3045
if (stream->txp_sent_fc) {
3046
stream->want_max_stream_data = 0;
3047
ossl_quic_rxfc_has_cwm_changed(&stream->rxfc, 1);
3048
}
3049
3050
if (stream->txp_sent_stop_sending)
3051
stream->want_stop_sending = 0;
3052
3053
if (stream->txp_sent_reset_stream)
3054
stream->want_reset_stream = 0;
3055
3056
if (stream->txp_txfc_new_credit_consumed > 0) {
3057
if (!ossl_assert(ossl_quic_txfc_consume_credit(&stream->txfc,
3058
stream->txp_txfc_new_credit_consumed)))
3059
/*
3060
* Should not be possible, but we should continue with our
3061
* bookkeeping as we have already committed the packet to the
3062
* FIFD. Just change the value we return.
3063
*/
3064
rc = 0;
3065
3066
stream->txp_txfc_new_credit_consumed = 0;
3067
}
3068
3069
/*
3070
* If we no longer need to generate any flow control (MAX_STREAM_DATA),
3071
* STOP_SENDING or RESET_STREAM frames, nor any STREAM frames (because
3072
* the stream is drained of data or TXFC-blocked), we can mark the
3073
* stream as inactive.
3074
*/
3075
ossl_quic_stream_map_update_state(txp->args.qsm, stream);
3076
3077
if (ossl_quic_stream_has_send_buffer(stream)
3078
&& !ossl_quic_sstream_has_pending(stream->sstream)
3079
&& ossl_quic_sstream_get_final_size(stream->sstream, NULL))
3080
/*
3081
* Transition to DATA_SENT if stream has a final size and we have
3082
* sent all data.
3083
*/
3084
ossl_quic_stream_map_notify_all_data_sent(txp->args.qsm, stream);
3085
}
3086
3087
/* We have now sent the packet, so update state accordingly. */
3088
if (tpkt->ackm_pkt.is_ack_eliciting)
3089
txp->force_ack_eliciting &= ~(1UL << pn_space);
3090
3091
if (tpkt->had_handshake_done_frame)
3092
txp->want_handshake_done = 0;
3093
3094
if (tpkt->had_max_data_frame) {
3095
txp->want_max_data = 0;
3096
ossl_quic_rxfc_has_cwm_changed(txp->args.conn_rxfc, 1);
3097
}
3098
3099
if (tpkt->had_max_streams_bidi_frame) {
3100
txp->want_max_streams_bidi = 0;
3101
ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_bidi_rxfc, 1);
3102
}
3103
3104
if (tpkt->had_max_streams_uni_frame) {
3105
txp->want_max_streams_uni = 0;
3106
ossl_quic_rxfc_has_cwm_changed(txp->args.max_streams_uni_rxfc, 1);
3107
}
3108
3109
if (tpkt->had_ack_frame)
3110
txp->want_ack &= ~(1UL << pn_space);
3111
3112
if (tpkt->had_conn_close)
3113
txp->want_conn_close = 0;
3114
3115
/*
3116
* Decrement probe request counts if we have sent a packet that meets
3117
* the requirement of a probe, namely being ACK-eliciting.
3118
*/
3119
if (tpkt->ackm_pkt.is_ack_eliciting) {
3120
OSSL_ACKM_PROBE_INFO *probe_info
3121
= ossl_ackm_get0_probe_request(txp->args.ackm);
3122
3123
if (enc_level == QUIC_ENC_LEVEL_INITIAL
3124
&& probe_info->anti_deadlock_initial > 0)
3125
--probe_info->anti_deadlock_initial;
3126
3127
if (enc_level == QUIC_ENC_LEVEL_HANDSHAKE
3128
&& probe_info->anti_deadlock_handshake > 0)
3129
--probe_info->anti_deadlock_handshake;
3130
3131
if (a.allow_force_ack_eliciting /* (i.e., not for 0-RTT) */
3132
&& probe_info->pto[pn_space] > 0)
3133
--probe_info->pto[pn_space];
3134
}
3135
3136
return rc;
3137
}
3138
3139
/* Ensure the iovec array is at least num elements long. */
3140
static int txp_el_ensure_iovec(struct txp_el *el, size_t num)
3141
{
3142
OSSL_QTX_IOVEC *iovec;
3143
3144
if (el->alloc_iovec >= num)
3145
return 1;
3146
3147
num = el->alloc_iovec != 0 ? el->alloc_iovec * 2 : 8;
3148
3149
iovec = OPENSSL_realloc(el->iovec, sizeof(OSSL_QTX_IOVEC) * num);
3150
if (iovec == NULL)
3151
return 0;
3152
3153
el->iovec = iovec;
3154
el->alloc_iovec = num;
3155
return 1;
3156
}
3157
3158
int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp,
3159
const OSSL_QUIC_FRAME_CONN_CLOSE *f)
3160
{
3161
char *reason = NULL;
3162
size_t reason_len = f->reason_len;
3163
size_t max_reason_len = txp_get_mdpl(txp) / 2;
3164
3165
if (txp->want_conn_close)
3166
return 0;
3167
3168
/*
3169
* Arbitrarily limit the length of the reason length string to half of the
3170
* MDPL.
3171
*/
3172
if (reason_len > max_reason_len)
3173
reason_len = max_reason_len;
3174
3175
if (reason_len > 0) {
3176
reason = OPENSSL_memdup(f->reason, reason_len);
3177
if (reason == NULL)
3178
return 0;
3179
}
3180
3181
txp->conn_close_frame = *f;
3182
txp->conn_close_frame.reason = reason;
3183
txp->conn_close_frame.reason_len = reason_len;
3184
txp->want_conn_close = 1;
3185
return 1;
3186
}
3187
3188
void ossl_quic_tx_packetiser_set_msg_callback(OSSL_QUIC_TX_PACKETISER *txp,
3189
ossl_msg_cb msg_callback,
3190
SSL *msg_callback_ssl)
3191
{
3192
txp->msg_callback = msg_callback;
3193
txp->msg_callback_ssl = msg_callback_ssl;
3194
}
3195
3196
void ossl_quic_tx_packetiser_set_msg_callback_arg(OSSL_QUIC_TX_PACKETISER *txp,
3197
void *msg_callback_arg)
3198
{
3199
txp->msg_callback_arg = msg_callback_arg;
3200
}
3201
3202
QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp,
3203
uint32_t pn_space)
3204
{
3205
if (pn_space >= QUIC_PN_SPACE_NUM)
3206
return UINT64_MAX;
3207
3208
return txp->next_pn[pn_space];
3209
}
3210
3211
OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp)
3212
{
3213
/*
3214
* TXP-specific deadline computations which rely on TXP innards. This is in
3215
* turn relied on by the QUIC_CHANNEL code to determine the channel event
3216
* handling deadline.
3217
*/
3218
OSSL_TIME deadline = ossl_time_infinite();
3219
uint32_t enc_level, pn_space;
3220
3221
/*
3222
* ACK generation is not CC-gated - packets containing only ACKs are allowed
3223
* to bypass CC. We want to generate ACK frames even if we are currently
3224
* restricted by CC so the peer knows we have received data. The generate
3225
* call will take care of selecting the correct packet archetype.
3226
*/
3227
for (enc_level = QUIC_ENC_LEVEL_INITIAL;
3228
enc_level < QUIC_ENC_LEVEL_NUM;
3229
++enc_level)
3230
if (ossl_qtx_is_enc_level_provisioned(txp->args.qtx, enc_level)) {
3231
pn_space = ossl_quic_enc_level_to_pn_space(enc_level);
3232
deadline = ossl_time_min(deadline,
3233
ossl_ackm_get_ack_deadline(txp->args.ackm, pn_space));
3234
}
3235
3236
/* When will CC let us send more? */
3237
if (txp->args.cc_method->get_tx_allowance(txp->args.cc_data) == 0)
3238
deadline = ossl_time_min(deadline,
3239
txp->args.cc_method->get_wakeup_deadline(txp->args.cc_data));
3240
3241
return deadline;
3242
}
3243
3244