1 /* 2 * Copyright 2022-2026 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_record_tx.h" 11 #include "internal/qlog_event_helpers.h" 12 #include "internal/bio_addr.h" 13 #include "internal/common.h" 14 #include "quic_record_shared.h" 15 #include "internal/list.h" 16 #include "../ssl_local.h" 17 18 /* 19 * TXE 20 * === 21 * Encrypted packets awaiting transmission are kept in TX Entries (TXEs), which 22 * are queued in linked lists just like TXEs. 23 */ 24 typedef struct txe_st TXE; 25 26 struct txe_st { 27 OSSL_LIST_MEMBER(txe, TXE); 28 size_t data_len, alloc_len; 29 30 /* 31 * Destination and local addresses, as applicable. Both of these are only 32 * used if the family is not AF_UNSPEC. 33 */ 34 BIO_ADDR peer, local; 35 36 /* 37 * alloc_len allocated bytes (of which data_len bytes are valid) follow this 38 * structure. 39 */ 40 }; 41 42 DEFINE_LIST_OF(txe, TXE); 43 typedef OSSL_LIST(txe) TXE_LIST; 44 45 static ossl_inline unsigned char *txe_data(const TXE *e) 46 { 47 return (unsigned char *)(e + 1); 48 } 49 50 /* 51 * QTX 52 * === 53 */ 54 struct ossl_qtx_st { 55 OSSL_LIB_CTX *libctx; 56 const char *propq; 57 58 /* Per encryption-level state. */ 59 OSSL_QRL_ENC_LEVEL_SET el_set; 60 61 /* TX BIO. */ 62 BIO *bio; 63 64 /* QLOG instance retrieval callback if in use, or NULL. */ 65 QLOG *(*get_qlog_cb)(void *arg); 66 void *get_qlog_cb_arg; 67 68 /* TX maximum datagram payload length. */ 69 size_t mdpl; 70 71 /* 72 * List of TXEs which are not currently in use. These are moved to the 73 * pending list (possibly via tx_cons first) as they are filled. 74 */ 75 TXE_LIST free; 76 77 /* 78 * List of TXEs which are filled with completed datagrams ready to be 79 * transmitted. 80 */ 81 TXE_LIST pending; 82 size_t pending_count; /* items in list */ 83 size_t pending_bytes; /* sum(txe->data_len) in pending */ 84 85 /* 86 * TXE which is under construction for coalescing purposes, if any. 87 * This TXE is neither on the free nor pending list. Once the datagram 88 * is completed, it is moved to the pending list. 89 */ 90 TXE *cons; 91 size_t cons_count; /* num packets */ 92 93 /* 94 * Number of packets transmitted in this key epoch. Used to enforce AEAD 95 * confidentiality limit. 96 */ 97 uint64_t epoch_pkt_count; 98 99 /* Datagram counter. Increases monotonically per datagram (not per packet). */ 100 uint64_t datagram_count; 101 102 ossl_mutate_packet_cb mutatecb; 103 ossl_finish_mutate_cb finishmutatecb; 104 void *mutatearg; 105 106 /* Message callback related arguments */ 107 ossl_msg_cb msg_callback; 108 void *msg_callback_arg; 109 SSL *msg_callback_ssl; 110 }; 111 112 /* Instantiates a new QTX. */ 113 OSSL_QTX *ossl_qtx_new(const OSSL_QTX_ARGS *args) 114 { 115 OSSL_QTX *qtx; 116 117 if (args->mdpl < QUIC_MIN_INITIAL_DGRAM_LEN) 118 return 0; 119 120 qtx = OPENSSL_zalloc(sizeof(OSSL_QTX)); 121 if (qtx == NULL) 122 return 0; 123 124 qtx->libctx = args->libctx; 125 qtx->propq = args->propq; 126 qtx->bio = args->bio; 127 qtx->mdpl = args->mdpl; 128 qtx->get_qlog_cb = args->get_qlog_cb; 129 qtx->get_qlog_cb_arg = args->get_qlog_cb_arg; 130 131 return qtx; 132 } 133 134 static void qtx_cleanup_txl(TXE_LIST *l) 135 { 136 TXE *e, *enext; 137 138 for (e = ossl_list_txe_head(l); e != NULL; e = enext) { 139 enext = ossl_list_txe_next(e); 140 OPENSSL_free(e); 141 } 142 } 143 144 /* Frees the QTX. */ 145 void ossl_qtx_free(OSSL_QTX *qtx) 146 { 147 uint32_t i; 148 149 if (qtx == NULL) 150 return; 151 152 /* Free TXE queue data. */ 153 qtx_cleanup_txl(&qtx->pending); 154 qtx_cleanup_txl(&qtx->free); 155 OPENSSL_free(qtx->cons); 156 157 /* Drop keying material and crypto resources. */ 158 for (i = 0; i < QUIC_ENC_LEVEL_NUM; ++i) 159 ossl_qrl_enc_level_set_discard(&qtx->el_set, i); 160 161 OPENSSL_free(qtx); 162 } 163 164 /* Set mutator callbacks for test framework support */ 165 void ossl_qtx_set_mutator(OSSL_QTX *qtx, ossl_mutate_packet_cb mutatecb, 166 ossl_finish_mutate_cb finishmutatecb, void *mutatearg) 167 { 168 qtx->mutatecb = mutatecb; 169 qtx->finishmutatecb = finishmutatecb; 170 qtx->mutatearg = mutatearg; 171 } 172 173 void ossl_qtx_set_qlog_cb(OSSL_QTX *qtx, QLOG *(*get_qlog_cb)(void *arg), 174 void *get_qlog_cb_arg) 175 { 176 qtx->get_qlog_cb = get_qlog_cb; 177 qtx->get_qlog_cb_arg = get_qlog_cb_arg; 178 } 179 180 int ossl_qtx_provide_secret(OSSL_QTX *qtx, 181 uint32_t enc_level, 182 uint32_t suite_id, 183 EVP_MD *md, 184 const unsigned char *secret, 185 size_t secret_len) 186 { 187 if (enc_level >= QUIC_ENC_LEVEL_NUM) 188 return 0; 189 190 return ossl_qrl_enc_level_set_provide_secret(&qtx->el_set, 191 qtx->libctx, 192 qtx->propq, 193 enc_level, 194 suite_id, 195 md, 196 secret, 197 secret_len, 198 0, 199 /*is_tx=*/1); 200 } 201 202 int ossl_qtx_discard_enc_level(OSSL_QTX *qtx, uint32_t enc_level) 203 { 204 if (enc_level >= QUIC_ENC_LEVEL_NUM) 205 return 0; 206 207 ossl_qrl_enc_level_set_discard(&qtx->el_set, enc_level); 208 return 1; 209 } 210 211 int ossl_qtx_is_enc_level_provisioned(OSSL_QTX *qtx, uint32_t enc_level) 212 { 213 return ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1) != NULL; 214 } 215 216 /* Allocate a new TXE. */ 217 static TXE *qtx_alloc_txe(size_t alloc_len) 218 { 219 TXE *txe; 220 221 if (alloc_len >= SIZE_MAX - sizeof(TXE)) 222 return NULL; 223 224 txe = OPENSSL_malloc(sizeof(TXE) + alloc_len); 225 if (txe == NULL) 226 return NULL; 227 228 ossl_list_txe_init_elem(txe); 229 txe->alloc_len = alloc_len; 230 txe->data_len = 0; 231 return txe; 232 } 233 234 /* 235 * Ensures there is at least one TXE in the free list, allocating a new entry 236 * if necessary. The returned TXE is in the free list; it is not popped. 237 * 238 * alloc_len is a hint which may be used to determine the TXE size if allocation 239 * is necessary. Returns NULL on allocation failure. 240 */ 241 static TXE *qtx_ensure_free_txe(OSSL_QTX *qtx, size_t alloc_len) 242 { 243 TXE *txe; 244 245 txe = ossl_list_txe_head(&qtx->free); 246 if (txe != NULL) 247 return txe; 248 249 txe = qtx_alloc_txe(alloc_len); 250 if (txe == NULL) 251 return NULL; 252 253 ossl_list_txe_insert_tail(&qtx->free, txe); 254 return txe; 255 } 256 257 /* 258 * Resize the data buffer attached to an TXE to be n bytes in size. The address 259 * of the TXE might change; the new address is returned, or NULL on failure, in 260 * which case the original TXE remains valid. 261 */ 262 static TXE *qtx_resize_txe(OSSL_QTX *qtx, TXE *txe, size_t n) 263 { 264 TXE *txe2; 265 266 /* Should never happen. */ 267 if (txe == NULL) 268 return NULL; 269 270 if (n >= SIZE_MAX - sizeof(TXE)) 271 return NULL; 272 273 /* 274 * to resize txe, the caller must detach it from the list first, 275 * fail if txe is still attached. 276 */ 277 if (!ossl_assert(ossl_list_txe_prev(txe) == NULL 278 && ossl_list_txe_next(txe) == NULL)) 279 return NULL; 280 281 /* 282 * NOTE: We do not clear old memory, although it does contain decrypted 283 * data. 284 */ 285 txe2 = OPENSSL_realloc(txe, sizeof(TXE) + n); 286 if (txe2 == NULL) 287 return NULL; 288 289 if (qtx->cons == txe) 290 qtx->cons = txe2; 291 292 txe2->alloc_len = n; 293 return txe2; 294 } 295 296 /* 297 * Ensure the data buffer attached to an TXE is at least n bytes in size. 298 * Returns NULL on failure. 299 */ 300 static TXE *qtx_reserve_txe(OSSL_QTX *qtx, TXE *txe, size_t n) 301 { 302 if (txe->alloc_len >= n) 303 return txe; 304 305 return qtx_resize_txe(qtx, txe, n); 306 } 307 308 /* Move a TXE from pending to free. */ 309 static void qtx_pending_to_free(OSSL_QTX *qtx) 310 { 311 TXE *txe = ossl_list_txe_head(&qtx->pending); 312 313 assert(txe != NULL); 314 ossl_list_txe_remove(&qtx->pending, txe); 315 --qtx->pending_count; 316 qtx->pending_bytes -= txe->data_len; 317 ossl_list_txe_insert_tail(&qtx->free, txe); 318 } 319 320 /* Add a TXE not currently in any list to the pending list. */ 321 static void qtx_add_to_pending(OSSL_QTX *qtx, TXE *txe) 322 { 323 ossl_list_txe_insert_tail(&qtx->pending, txe); 324 ++qtx->pending_count; 325 qtx->pending_bytes += txe->data_len; 326 } 327 328 struct iovec_cur { 329 const OSSL_QTX_IOVEC *iovec; 330 size_t num_iovec, idx, byte_off, bytes_remaining; 331 }; 332 333 static size_t iovec_total_bytes(const OSSL_QTX_IOVEC *iovec, 334 size_t num_iovec) 335 { 336 size_t i, l = 0; 337 338 for (i = 0; i < num_iovec; ++i) 339 l += iovec[i].buf_len; 340 341 return l; 342 } 343 344 static void iovec_cur_init(struct iovec_cur *cur, 345 const OSSL_QTX_IOVEC *iovec, 346 size_t num_iovec) 347 { 348 cur->iovec = iovec; 349 cur->num_iovec = num_iovec; 350 cur->idx = 0; 351 cur->byte_off = 0; 352 cur->bytes_remaining = iovec_total_bytes(iovec, num_iovec); 353 } 354 355 /* 356 * Get an extent of bytes from the iovec cursor. *buf is set to point to the 357 * buffer and the number of bytes in length of the buffer is returned. This 358 * value may be less than the max_buf_len argument. If no more data is 359 * available, returns 0. 360 */ 361 static size_t iovec_cur_get_buffer(struct iovec_cur *cur, 362 const unsigned char **buf, 363 size_t max_buf_len) 364 { 365 size_t l; 366 367 if (max_buf_len == 0) { 368 *buf = NULL; 369 return 0; 370 } 371 372 for (;;) { 373 if (cur->idx >= cur->num_iovec) 374 return 0; 375 376 l = cur->iovec[cur->idx].buf_len - cur->byte_off; 377 if (l > max_buf_len) 378 l = max_buf_len; 379 380 if (l > 0) { 381 *buf = cur->iovec[cur->idx].buf + cur->byte_off; 382 cur->byte_off += l; 383 cur->bytes_remaining -= l; 384 return l; 385 } 386 387 /* 388 * Zero-length iovec entry or we already consumed all of it, try the 389 * next iovec. 390 */ 391 ++cur->idx; 392 cur->byte_off = 0; 393 } 394 } 395 396 /* Determines the size of the AEAD output given the input size. */ 397 int ossl_qtx_calculate_ciphertext_payload_len(OSSL_QTX *qtx, uint32_t enc_level, 398 size_t plaintext_len, 399 size_t *ciphertext_len) 400 { 401 OSSL_QRL_ENC_LEVEL *el 402 = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 403 size_t tag_len; 404 405 if (el == NULL) { 406 *ciphertext_len = 0; 407 return 0; 408 } 409 410 /* 411 * We currently only support ciphers with a 1:1 mapping between plaintext 412 * and ciphertext size, save for authentication tag. 413 */ 414 tag_len = ossl_qrl_get_suite_cipher_tag_len(el->suite_id); 415 416 *ciphertext_len = plaintext_len + tag_len; 417 return 1; 418 } 419 420 /* Determines the size of the AEAD input given the output size. */ 421 int ossl_qtx_calculate_plaintext_payload_len(OSSL_QTX *qtx, uint32_t enc_level, 422 size_t ciphertext_len, 423 size_t *plaintext_len) 424 { 425 OSSL_QRL_ENC_LEVEL *el 426 = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 427 size_t tag_len; 428 429 if (el == NULL) { 430 *plaintext_len = 0; 431 return 0; 432 } 433 434 tag_len = ossl_qrl_get_suite_cipher_tag_len(el->suite_id); 435 436 if (ciphertext_len <= tag_len) { 437 *plaintext_len = 0; 438 return 0; 439 } 440 441 *plaintext_len = ciphertext_len - tag_len; 442 return 1; 443 } 444 445 /* Any other error (including packet being too big for MDPL). */ 446 #define QTX_FAIL_GENERIC (-1) 447 448 /* 449 * Returned where there is insufficient room in the datagram to write the 450 * packet. 451 */ 452 #define QTX_FAIL_INSUFFICIENT_LEN (-2) 453 454 static int qtx_write_hdr(OSSL_QTX *qtx, const QUIC_PKT_HDR *hdr, TXE *txe, 455 QUIC_PKT_HDR_PTRS *ptrs) 456 { 457 WPACKET wpkt; 458 size_t l = 0; 459 unsigned char *data = txe_data(txe) + txe->data_len; 460 461 if (!WPACKET_init_static_len(&wpkt, data, txe->alloc_len - txe->data_len, 0)) 462 return 0; 463 464 if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr->dst_conn_id.id_len, 465 hdr, ptrs) 466 || !WPACKET_get_total_written(&wpkt, &l)) { 467 WPACKET_finish(&wpkt); 468 return 0; 469 } 470 WPACKET_finish(&wpkt); 471 472 if (qtx->msg_callback != NULL) 473 qtx->msg_callback(1, OSSL_QUIC1_VERSION, SSL3_RT_QUIC_PACKET, data, l, 474 qtx->msg_callback_ssl, qtx->msg_callback_arg); 475 476 txe->data_len += l; 477 478 return 1; 479 } 480 481 static int qtx_encrypt_into_txe(OSSL_QTX *qtx, struct iovec_cur *cur, TXE *txe, 482 uint32_t enc_level, QUIC_PN pn, 483 const unsigned char *hdr, size_t hdr_len, 484 QUIC_PKT_HDR_PTRS *ptrs) 485 { 486 int l = 0, l2 = 0, nonce_len; 487 OSSL_QRL_ENC_LEVEL *el 488 = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 489 unsigned char nonce[EVP_MAX_IV_LENGTH]; 490 size_t i; 491 EVP_CIPHER_CTX *cctx = NULL; 492 493 /* We should not have been called if we do not have key material. */ 494 if (!ossl_assert(el != NULL)) { 495 ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); 496 return 0; 497 } 498 499 /* 500 * Have we already encrypted the maximum number of packets using the current 501 * key? 502 */ 503 if (el->op_count >= ossl_qrl_get_suite_max_pkt(el->suite_id)) { 504 ERR_raise(ERR_LIB_SSL, SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED); 505 return 0; 506 } 507 508 /* 509 * TX key update is simpler than for RX; once we initiate a key update, we 510 * never need the old keys, as we never deliberately send a packet with old 511 * keys. Thus the EL always uses keyslot 0 for the TX side. 512 */ 513 cctx = el->cctx[0]; 514 if (!ossl_assert(cctx != NULL)) { 515 ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); 516 return 0; 517 } 518 519 /* Construct nonce (nonce=IV ^ PN). */ 520 nonce_len = EVP_CIPHER_CTX_get_iv_length(cctx); 521 if (!ossl_assert(nonce_len >= (int)sizeof(QUIC_PN))) { 522 ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); 523 return 0; 524 } 525 526 memcpy(nonce, el->iv[0], (size_t)nonce_len); 527 for (i = 0; i < sizeof(QUIC_PN); ++i) 528 nonce[nonce_len - i - 1] ^= (unsigned char)(pn >> (i * 8)); 529 530 /* type and key will already have been setup; feed the IV. */ 531 if (EVP_CipherInit_ex(cctx, NULL, NULL, NULL, nonce, /*enc=*/1) != 1) { 532 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB); 533 return 0; 534 } 535 536 /* Feed AAD data. */ 537 if (EVP_CipherUpdate(cctx, NULL, &l, hdr, hdr_len) != 1) { 538 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB); 539 return 0; 540 } 541 542 /* Encrypt plaintext directly into TXE. */ 543 for (;;) { 544 const unsigned char *src; 545 size_t src_len; 546 547 src_len = iovec_cur_get_buffer(cur, &src, SIZE_MAX); 548 if (src_len == 0) 549 break; 550 551 if (EVP_CipherUpdate(cctx, txe_data(txe) + txe->data_len, 552 &l, src, src_len) 553 != 1) { 554 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB); 555 return 0; 556 } 557 558 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 559 /* Ignore what we just encrypted and overwrite it with the plaintext */ 560 memcpy(txe_data(txe) + txe->data_len, src, l); 561 #endif 562 563 assert(l > 0 && src_len == (size_t)l); 564 txe->data_len += src_len; 565 } 566 567 /* Finalise and get tag. */ 568 if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) { 569 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB); 570 return 0; 571 } 572 573 if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG, 574 el->tag_len, txe_data(txe) + txe->data_len) 575 != 1) { 576 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB); 577 return 0; 578 } 579 580 txe->data_len += el->tag_len; 581 582 /* Apply header protection. */ 583 if (!ossl_quic_hdr_protector_encrypt(&el->hpr, ptrs)) 584 return 0; 585 586 ++el->op_count; 587 return 1; 588 } 589 590 /* 591 * Append a packet to the TXE buffer, serializing and encrypting it in the 592 * process. 593 */ 594 static int qtx_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe, 595 uint32_t enc_level, QUIC_PKT_HDR *hdr, 596 const OSSL_QTX_IOVEC *iovec, size_t num_iovec) 597 { 598 int ret, needs_encrypt; 599 size_t hdr_len, pred_hdr_len, payload_len, pkt_len, space_left; 600 size_t min_len, orig_data_len; 601 struct iovec_cur cur; 602 QUIC_PKT_HDR_PTRS ptrs; 603 unsigned char *hdr_start; 604 OSSL_QRL_ENC_LEVEL *el = NULL; 605 606 /* 607 * Determine if the packet needs encryption and the minimum conceivable 608 * serialization length. 609 */ 610 if (!ossl_quic_pkt_type_is_encrypted(hdr->type)) { 611 needs_encrypt = 0; 612 min_len = QUIC_MIN_VALID_PKT_LEN; 613 } else { 614 needs_encrypt = 1; 615 min_len = QUIC_MIN_VALID_PKT_LEN_CRYPTO; 616 el = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 617 if (!ossl_assert(el != NULL)) /* should already have been checked */ 618 return 0; 619 } 620 621 orig_data_len = txe->data_len; 622 space_left = txe->alloc_len - txe->data_len; 623 if (space_left < min_len) { 624 /* Not even a possibility of it fitting. */ 625 ret = QTX_FAIL_INSUFFICIENT_LEN; 626 goto err; 627 } 628 629 /* Set some fields in the header we are responsible for. */ 630 if (hdr->type == QUIC_PKT_TYPE_1RTT) 631 hdr->key_phase = (unsigned char)(el->key_epoch & 1); 632 633 /* Walk the iovecs to determine actual input payload length. */ 634 iovec_cur_init(&cur, iovec, num_iovec); 635 636 if (cur.bytes_remaining == 0) { 637 /* No zero-length payloads allowed. */ 638 ret = QTX_FAIL_GENERIC; 639 goto err; 640 } 641 642 /* Determine encrypted payload length. */ 643 if (needs_encrypt) 644 ossl_qtx_calculate_ciphertext_payload_len(qtx, enc_level, 645 cur.bytes_remaining, 646 &payload_len); 647 else 648 payload_len = cur.bytes_remaining; 649 650 /* Determine header length. */ 651 hdr->data = NULL; 652 hdr->len = payload_len; 653 pred_hdr_len = ossl_quic_wire_get_encoded_pkt_hdr_len(hdr->dst_conn_id.id_len, 654 hdr); 655 if (pred_hdr_len == 0) { 656 ret = QTX_FAIL_GENERIC; 657 goto err; 658 } 659 660 /* We now definitively know our packet length. */ 661 pkt_len = pred_hdr_len + payload_len; 662 663 if (pkt_len > space_left) { 664 ret = QTX_FAIL_INSUFFICIENT_LEN; 665 goto err; 666 } 667 668 if (ossl_quic_pkt_type_has_pn(hdr->type)) { 669 if (!ossl_quic_wire_encode_pkt_hdr_pn(pkt->pn, 670 hdr->pn, 671 hdr->pn_len)) { 672 ret = QTX_FAIL_GENERIC; 673 goto err; 674 } 675 } 676 677 /* Append the header to the TXE. */ 678 hdr_start = txe_data(txe) + txe->data_len; 679 if (!qtx_write_hdr(qtx, hdr, txe, &ptrs)) { 680 ret = QTX_FAIL_GENERIC; 681 goto err; 682 } 683 684 hdr_len = (txe_data(txe) + txe->data_len) - hdr_start; 685 assert(hdr_len == pred_hdr_len); 686 687 if (!needs_encrypt) { 688 /* Just copy the payload across. */ 689 const unsigned char *src; 690 size_t src_len; 691 692 for (;;) { 693 /* Buffer length has already been checked above. */ 694 src_len = iovec_cur_get_buffer(&cur, &src, SIZE_MAX); 695 if (src_len == 0) 696 break; 697 698 memcpy(txe_data(txe) + txe->data_len, src, src_len); 699 txe->data_len += src_len; 700 } 701 } else { 702 /* Encrypt into TXE. */ 703 if (!qtx_encrypt_into_txe(qtx, &cur, txe, enc_level, pkt->pn, 704 hdr_start, hdr_len, &ptrs)) { 705 ret = QTX_FAIL_GENERIC; 706 goto err; 707 } 708 709 assert(txe->data_len - orig_data_len == pkt_len); 710 } 711 712 return 1; 713 714 err: 715 /* 716 * Restore original length so we don't leave a half-written packet in the 717 * TXE. 718 */ 719 txe->data_len = orig_data_len; 720 return ret; 721 } 722 723 static TXE *qtx_ensure_cons(OSSL_QTX *qtx) 724 { 725 TXE *txe = qtx->cons; 726 727 if (txe != NULL) 728 return txe; 729 730 txe = qtx_ensure_free_txe(qtx, qtx->mdpl); 731 if (txe == NULL) 732 return NULL; 733 734 ossl_list_txe_remove(&qtx->free, txe); 735 qtx->cons = txe; 736 qtx->cons_count = 0; 737 txe->data_len = 0; 738 return txe; 739 } 740 741 static QLOG *qtx_get_qlog(OSSL_QTX *qtx) 742 { 743 if (qtx->get_qlog_cb == NULL) 744 return NULL; 745 746 return qtx->get_qlog_cb(qtx->get_qlog_cb_arg); 747 } 748 749 static int qtx_mutate_write(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt, TXE *txe, 750 uint32_t enc_level) 751 { 752 int ret; 753 QUIC_PKT_HDR *hdr; 754 const OSSL_QTX_IOVEC *iovec; 755 size_t num_iovec; 756 757 /* If we are running tests then mutate_packet may be non NULL */ 758 if (qtx->mutatecb != NULL) { 759 if (!qtx->mutatecb(pkt->hdr, pkt->iovec, pkt->num_iovec, &hdr, 760 &iovec, &num_iovec, qtx->mutatearg)) 761 return QTX_FAIL_GENERIC; 762 } else { 763 hdr = pkt->hdr; 764 iovec = pkt->iovec; 765 num_iovec = pkt->num_iovec; 766 } 767 768 ret = qtx_write(qtx, pkt, txe, enc_level, 769 hdr, iovec, num_iovec); 770 if (ret == 1) 771 ossl_qlog_event_transport_packet_sent(qtx_get_qlog(qtx), hdr, pkt->pn, 772 iovec, num_iovec, 773 qtx->datagram_count); 774 775 if (qtx->finishmutatecb != NULL) 776 qtx->finishmutatecb(qtx->mutatearg); 777 778 return ret; 779 } 780 781 static int addr_eq(const BIO_ADDR *a, const BIO_ADDR *b) 782 { 783 return ((a == NULL || BIO_ADDR_family(a) == AF_UNSPEC) 784 && (b == NULL || BIO_ADDR_family(b) == AF_UNSPEC)) 785 || (a != NULL && b != NULL && memcmp(a, b, sizeof(*a)) == 0); 786 } 787 788 int ossl_qtx_write_pkt(OSSL_QTX *qtx, const OSSL_QTX_PKT *pkt) 789 { 790 int ret; 791 int coalescing = (pkt->flags & OSSL_QTX_PKT_FLAG_COALESCE) != 0; 792 int was_coalescing; 793 TXE *txe; 794 uint32_t enc_level; 795 796 /* Must have EL configured, must have header. */ 797 if (pkt->hdr == NULL) 798 return 0; 799 800 enc_level = ossl_quic_pkt_type_to_enc_level(pkt->hdr->type); 801 802 /* Some packet types must be in a packet all by themselves. */ 803 if (!ossl_quic_pkt_type_can_share_dgram(pkt->hdr->type)) 804 ossl_qtx_finish_dgram(qtx); 805 else if (enc_level >= QUIC_ENC_LEVEL_NUM 806 || ossl_qrl_enc_level_set_have_el(&qtx->el_set, enc_level) != 1) { 807 /* All other packet types are encrypted. */ 808 return 0; 809 } 810 811 was_coalescing = (qtx->cons != NULL && qtx->cons->data_len > 0); 812 if (was_coalescing) 813 if (!addr_eq(&qtx->cons->peer, pkt->peer) 814 || !addr_eq(&qtx->cons->local, pkt->local)) { 815 /* Must stop coalescing if addresses have changed */ 816 ossl_qtx_finish_dgram(qtx); 817 was_coalescing = 0; 818 } 819 820 for (;;) { 821 /* 822 * Start a new coalescing session or continue using the existing one and 823 * serialize/encrypt the packet. We always encrypt packets as soon as 824 * our caller gives them to us, which relieves the caller of any need to 825 * keep the plaintext around. 826 * 827 * the txe can have three distinct states: 828 * - attached to free list 829 * - attached to tx list 830 * - detached. 831 * 832 * if txe is detached (not member of free/tx list), then it is kept 833 * in qtx->cons. The qtx_ensure_cons() here either returns the txe 834 * from free list or existing ->cons txe. The txe we obtain here 835 * is detached. 836 */ 837 txe = qtx_ensure_cons(qtx); 838 if (txe == NULL) 839 return 0; /* allocation failure */ 840 841 /* 842 * Ensure TXE has at least MDPL bytes allocated. This should only be 843 * possible if the MDPL has increased. 844 */ 845 txe = qtx_reserve_txe(qtx, txe, qtx->mdpl); 846 if (txe == NULL) { 847 /* 848 * realloc of txe failed. however it is still kept in ->cons, 849 * no memory leak. 850 * The question is what we should do here to handle error, 851 * is doing `return 0` enough? or shall we discard ->cons and 852 * put it back to free list? 853 * or just stop coalescing the packet and dispatch it to network 854 * right now so the next packet tx can start from fresh? 855 * I think this is the problem for another day. 856 */ 857 return 0; 858 } 859 860 if (!was_coalescing) { 861 /* Set addresses in TXE. */ 862 if (pkt->peer != NULL) { 863 if (!BIO_ADDR_copy(&txe->peer, pkt->peer)) 864 return 0; 865 } else { 866 BIO_ADDR_clear(&txe->peer); 867 } 868 869 if (pkt->local != NULL) { 870 if (!BIO_ADDR_copy(&txe->local, pkt->local)) 871 return 0; 872 } else { 873 BIO_ADDR_clear(&txe->local); 874 } 875 } 876 877 ret = qtx_mutate_write(qtx, pkt, txe, enc_level); 878 if (ret == 1) { 879 break; 880 } else if (ret == QTX_FAIL_INSUFFICIENT_LEN) { 881 if (was_coalescing) { 882 /* 883 * We failed due to insufficient length, so end the current 884 * datagram and try again. 885 * 886 * the ossl_qtx_finish_dgram() also puts the txe (-.cons) to 887 * tx list, so ->cons becomes attached again. The function also 888 * sets ->cons to NULL so the next loop iteration starts with 889 * fresh txe (which is also safe to resize). 890 */ 891 ossl_qtx_finish_dgram(qtx); 892 was_coalescing = 0; 893 } else { 894 /* 895 * We failed due to insufficient length, but we were not 896 * coalescing/started with an empty datagram, so any future 897 * attempt to write this packet must also fail. 898 */ 899 return 0; 900 } 901 } else { 902 return 0; /* other error */ 903 } 904 } 905 906 ++qtx->cons_count; 907 908 /* 909 * Some packet types cannot have another packet come after them. 910 */ 911 if (ossl_quic_pkt_type_must_be_last(pkt->hdr->type)) 912 coalescing = 0; 913 914 if (!coalescing) 915 ossl_qtx_finish_dgram(qtx); 916 917 return 1; 918 } 919 920 /* 921 * Finish any incomplete datagrams for transmission which were flagged for 922 * coalescing. If there is no current coalescing datagram, this is a no-op. 923 */ 924 void ossl_qtx_finish_dgram(OSSL_QTX *qtx) 925 { 926 TXE *txe = qtx->cons; 927 928 if (txe == NULL) 929 return; 930 931 if (txe->data_len == 0) 932 /* 933 * If we did not put anything in the datagram, just move it back to the 934 * free list. 935 */ 936 ossl_list_txe_insert_tail(&qtx->free, txe); 937 else 938 qtx_add_to_pending(qtx, txe); 939 940 qtx->cons = NULL; 941 qtx->cons_count = 0; 942 ++qtx->datagram_count; 943 } 944 945 static void txe_to_msg(TXE *txe, BIO_MSG *msg) 946 { 947 msg->data = txe_data(txe); 948 msg->data_len = txe->data_len; 949 msg->flags = 0; 950 msg->peer 951 = BIO_ADDR_family(&txe->peer) != AF_UNSPEC ? &txe->peer : NULL; 952 msg->local 953 = BIO_ADDR_family(&txe->local) != AF_UNSPEC ? &txe->local : NULL; 954 } 955 956 #define MAX_MSGS_PER_SEND 32 957 958 int ossl_qtx_flush_net(OSSL_QTX *qtx) 959 { 960 BIO_MSG msg[MAX_MSGS_PER_SEND]; 961 size_t wr, i, total_written = 0; 962 TXE *txe; 963 int res; 964 965 if (ossl_list_txe_head(&qtx->pending) == NULL) 966 return QTX_FLUSH_NET_RES_OK; /* Nothing to send. */ 967 968 if (qtx->bio == NULL) 969 return QTX_FLUSH_NET_RES_PERMANENT_FAIL; 970 971 for (;;) { 972 for (txe = ossl_list_txe_head(&qtx->pending), i = 0; 973 txe != NULL && i < OSSL_NELEM(msg); 974 txe = ossl_list_txe_next(txe), ++i) 975 txe_to_msg(txe, &msg[i]); 976 977 if (!i) 978 /* Nothing to send. */ 979 break; 980 981 ERR_set_mark(); 982 res = BIO_sendmmsg(qtx->bio, msg, sizeof(BIO_MSG), i, 0, &wr); 983 if (res && wr == 0) { 984 /* 985 * Treat 0 messages sent as a transient error and just stop for now. 986 */ 987 ERR_clear_last_mark(); 988 break; 989 } else if (!res) { 990 /* 991 * We did not get anything, so further calls will probably not 992 * succeed either. 993 */ 994 if (BIO_err_is_non_fatal(ERR_peek_last_error())) { 995 /* Transient error, just stop for now, clearing the error. */ 996 ERR_pop_to_mark(); 997 break; 998 } else { 999 /* Non-transient error, fail and do not clear the error. */ 1000 ERR_clear_last_mark(); 1001 return QTX_FLUSH_NET_RES_PERMANENT_FAIL; 1002 } 1003 } 1004 1005 ERR_clear_last_mark(); 1006 1007 /* 1008 * Remove everything which was successfully sent from the pending queue. 1009 */ 1010 for (i = 0; i < wr; ++i) { 1011 if (qtx->msg_callback != NULL) 1012 qtx->msg_callback(1, OSSL_QUIC1_VERSION, SSL3_RT_QUIC_DATAGRAM, 1013 msg[i].data, msg[i].data_len, 1014 qtx->msg_callback_ssl, 1015 qtx->msg_callback_arg); 1016 qtx_pending_to_free(qtx); 1017 } 1018 1019 total_written += wr; 1020 } 1021 1022 return total_written > 0 1023 ? QTX_FLUSH_NET_RES_OK 1024 : QTX_FLUSH_NET_RES_TRANSIENT_FAIL; 1025 } 1026 1027 int ossl_qtx_pop_net(OSSL_QTX *qtx, BIO_MSG *msg) 1028 { 1029 TXE *txe = ossl_list_txe_head(&qtx->pending); 1030 1031 if (txe == NULL) 1032 return 0; 1033 1034 txe_to_msg(txe, msg); 1035 qtx_pending_to_free(qtx); 1036 return 1; 1037 } 1038 1039 void ossl_qtx_set_bio(OSSL_QTX *qtx, BIO *bio) 1040 { 1041 qtx->bio = bio; 1042 } 1043 1044 int ossl_qtx_set_mdpl(OSSL_QTX *qtx, size_t mdpl) 1045 { 1046 if (mdpl < QUIC_MIN_INITIAL_DGRAM_LEN) 1047 return 0; 1048 1049 qtx->mdpl = mdpl; 1050 return 1; 1051 } 1052 1053 size_t ossl_qtx_get_mdpl(OSSL_QTX *qtx) 1054 { 1055 return qtx->mdpl; 1056 } 1057 1058 size_t ossl_qtx_get_queue_len_datagrams(OSSL_QTX *qtx) 1059 { 1060 return qtx->pending_count; 1061 } 1062 1063 size_t ossl_qtx_get_queue_len_bytes(OSSL_QTX *qtx) 1064 { 1065 return qtx->pending_bytes; 1066 } 1067 1068 size_t ossl_qtx_get_cur_dgram_len_bytes(OSSL_QTX *qtx) 1069 { 1070 return qtx->cons != NULL ? qtx->cons->data_len : 0; 1071 } 1072 1073 size_t ossl_qtx_get_unflushed_pkt_count(OSSL_QTX *qtx) 1074 { 1075 return qtx->cons_count; 1076 } 1077 1078 int ossl_qtx_trigger_key_update(OSSL_QTX *qtx) 1079 { 1080 return ossl_qrl_enc_level_set_key_update(&qtx->el_set, 1081 QUIC_ENC_LEVEL_1RTT); 1082 } 1083 1084 uint64_t ossl_qtx_get_cur_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level) 1085 { 1086 OSSL_QRL_ENC_LEVEL *el; 1087 1088 el = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 1089 if (el == NULL) 1090 return UINT64_MAX; 1091 1092 return el->op_count; 1093 } 1094 1095 uint64_t ossl_qtx_get_max_epoch_pkt_count(OSSL_QTX *qtx, uint32_t enc_level) 1096 { 1097 OSSL_QRL_ENC_LEVEL *el; 1098 1099 el = ossl_qrl_enc_level_set_get(&qtx->el_set, enc_level, 1); 1100 if (el == NULL) 1101 return UINT64_MAX; 1102 1103 return ossl_qrl_get_suite_max_pkt(el->suite_id); 1104 } 1105 1106 void ossl_qtx_set_msg_callback(OSSL_QTX *qtx, ossl_msg_cb msg_callback, 1107 SSL *msg_callback_ssl) 1108 { 1109 qtx->msg_callback = msg_callback; 1110 qtx->msg_callback_ssl = msg_callback_ssl; 1111 } 1112 1113 void ossl_qtx_set_msg_callback_arg(OSSL_QTX *qtx, void *msg_callback_arg) 1114 { 1115 qtx->msg_callback_arg = msg_callback_arg; 1116 } 1117 1118 uint64_t ossl_qtx_get_key_epoch(OSSL_QTX *qtx) 1119 { 1120 OSSL_QRL_ENC_LEVEL *el; 1121 1122 el = ossl_qrl_enc_level_set_get(&qtx->el_set, QUIC_ENC_LEVEL_1RTT, 1); 1123 if (el == NULL) 1124 return 0; 1125 1126 return el->key_epoch; 1127 } 1128