diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/quic/quic_ackm.c | 33 | ||||
-rw-r--r-- | ssl/quic/quic_channel.c | 3 | ||||
-rw-r--r-- | ssl/quic/quic_rx_depack.c | 28 |
3 files changed, 33 insertions, 31 deletions
diff --git a/ssl/quic/quic_ackm.c b/ssl/quic/quic_ackm.c index 75a1e5741a03..93c83a36d8fe 100644 --- a/ssl/quic/quic_ackm.c +++ b/ssl/quic/quic_ackm.c @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -536,6 +536,9 @@ struct ossl_ackm_st { /* Set to 1 when the handshake is confirmed. */ char handshake_confirmed; + /* Set to 1 when attached to server channel */ + char is_server; + /* Set to 1 when the peer has completed address validation. */ char peer_completed_addr_validation; @@ -855,7 +858,13 @@ static OSSL_TIME ackm_get_pto_time_and_space(OSSL_ACKM *ackm, int *space) } for (i = QUIC_PN_SPACE_INITIAL; i < QUIC_PN_SPACE_NUM; ++i) { - if (ackm->ack_eliciting_bytes_in_flight[i] == 0) + /* + * RFC 9002 section 6.2.2.1 keep probe timeout armed until + * handshake is confirmed (client sees HANDSHAKE_DONE message + * from server). + */ + if (ackm->ack_eliciting_bytes_in_flight[i] == 0 && + (ackm->handshake_confirmed == 1 || ackm->is_server == 1)) continue; if (i == QUIC_PN_SPACE_APP) { @@ -875,10 +884,18 @@ static OSSL_TIME ackm_get_pto_time_and_space(OSSL_ACKM *ackm, int *space) } } - t = ossl_time_add(ackm->time_of_last_ack_eliciting_pkt[i], duration); - if (ossl_time_compare(t, pto_timeout) < 0) { - pto_timeout = t; - pto_space = i; + /* + * Only re-arm timer if stack has sent at least one ACK eliciting frame. + * If stack has sent no ACK eliciting frame at given encryption level then + * particular timer is zero and we must not attempt to set it. Timer keeps + * time since epoch (Jan 1 1970) and we must not set timer to past. + */ + if (!ossl_time_is_zero(ackm->time_of_last_ack_eliciting_pkt[i])) { + t = ossl_time_add(ackm->time_of_last_ack_eliciting_pkt[i], duration); + if (ossl_time_compare(t, pto_timeout) < 0) { + pto_timeout = t; + pto_space = i; + } } } @@ -1021,7 +1038,8 @@ OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg), void *now_arg, OSSL_STATM *statm, const OSSL_CC_METHOD *cc_method, - OSSL_CC_DATA *cc_data) + OSSL_CC_DATA *cc_data, + int is_server) { OSSL_ACKM *ackm; int i; @@ -1045,6 +1063,7 @@ OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg), ackm->statm = statm; ackm->cc_method = cc_method; ackm->cc_data = cc_data; + ackm->is_server = (char)is_server; ackm->rx_max_ack_delay = ossl_ms2time(QUIC_DEFAULT_MAX_ACK_DELAY); ackm->tx_max_ack_delay = DEFAULT_TX_MAX_ACK_DELAY; diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 8fb651d9ceb6..f8e4252ba48f 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -242,7 +242,8 @@ static int ch_init(QUIC_CHANNEL *ch) goto err; if ((ch->ackm = ossl_ackm_new(get_time, ch, &ch->statm, - ch->cc_method, ch->cc_data)) == NULL) + ch->cc_method, ch->cc_data, + ch->is_server)) == NULL) goto err; if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch, diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c index a36b02d5dcb4..f800d8984193 100644 --- a/ssl/quic/quic_rx_depack.c +++ b/ssl/quic/quic_rx_depack.c @@ -1429,16 +1429,8 @@ int ossl_quic_handle_frames(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpacket) uint32_t enc_level; size_t dgram_len = qpacket->datagram_len; - /* - * ok has three states: - * -1 error with ackm_data uninitialized - * 0 error with ackm_data initialized - * 1 success (ackm_data initialized) - */ - int ok = -1; /* Assume the worst */ - if (ch == NULL) - goto end; + return 0; ch->did_crypto_frame = 0; @@ -1456,9 +1448,8 @@ int ossl_quic_handle_frames(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpacket) * Retry and Version Negotiation packets should not be passed to this * function. */ - goto end; + return 0; - ok = 0; /* Still assume the worst */ ackm_data.pkt_space = ossl_quic_enc_level_to_pn_space(enc_level); /* @@ -1480,18 +1471,9 @@ int ossl_quic_handle_frames(QUIC_CHANNEL *ch, OSSL_QRX_PKT *qpacket) enc_level, qpacket->time, &ackm_data)) - goto end; + return 0; - ok = 1; - end: - /* - * ASSUMPTION: If this function is called at all, |qpacket| is - * a legitimate packet, even if its contents aren't. - * Therefore, we call ossl_ackm_on_rx_packet() unconditionally, as long as - * |ackm_data| has at least been initialized. - */ - if (ok >= 0) - ossl_ackm_on_rx_packet(ch->ackm, &ackm_data); + ossl_ackm_on_rx_packet(ch->ackm, &ackm_data); - return ok > 0; + return 1; } |